Observabilidade refere-se à capacidade de um objeto de notificar outras pessoas sobre mudanças nos dados dele. A Data Binding Library permite tornar objetos, campos ou coleções observáveis.
Você pode usar qualquer objeto para vinculação de dados, mas a modificação do objeto não faz com que a IU seja atualizada automaticamente. É possível usar a vinculação de dados para que seus objetos de dados notifiquem outros objetos, conhecidos como listeners, quando os dados mudarem. Há três tipos de classes observáveis: campos, coleções e objetos.
Quando um desses objetos de dados observáveis é vinculado à interface e uma propriedade do objeto de dados muda, a interface é atualizada automaticamente.
Campos observáveis
Caso suas classes tenham apenas algumas propriedades, talvez não valha a pena
criar classes que implementem a
interface Observable
. Nesse
caso, você pode usar a classe genérica Observable
e as classes
específicas de primitivos abaixo para tornar os campos observáveis:
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
Os campos observáveis são objetos observáveis independentes que têm um único
campo. As versões primitivas evitam o boxe e o unboxing durante as operações
de acesso. Para usar esse mecanismo, crie uma propriedade public final
na linguagem de programação
Java ou uma propriedade somente leitura em Kotlin, conforme mostrado no
exemplo abaixo:
Kotlin
class User { val firstName = ObservableField<String>() val lastName = ObservableField<String>() val age = ObservableInt() }
Java
private static class User { public final ObservableField<String> firstName = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt(); }
Para acessar o valor do campo, use os métodos do acessador
set()
e
get()
ou use a sintaxe de propriedade
do Kotlin:
Kotlin
user.firstName = "Google" val age = user.age
Java
user.firstName.set("Google"); int age = user.age.get();
Coleções observáveis
Alguns apps usam estruturas dinâmicas para reter dados. As coleções observáveis permitem
acessar essas estruturas usando uma chave. A
classe ObservableArrayMap
é útil quando a chave é um tipo de referência, por exemplo, String
, conforme mostrado no
exemplo a seguir.
Kotlin
ObservableArrayMap<String, Any>().apply { put("firstName", "Google") put("lastName", "Inc.") put("age", 17) }
Java
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>(); user.put("firstName", "Google"); user.put("lastName", "Inc."); user.put("age", 17);
No layout, você encontra o mapa usando as chaves de string, como mostrado no exemplo a seguir:
<data>
<import type="android.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{String.valueOf(1 + (Integer)user.age)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
A classe ObservableArrayList
é útil quando a chave é um número inteiro, como mostrado a seguir:
Kotlin
ObservableArrayList<Any>().apply { add("Google") add("Inc.") add(17) }
Java
ObservableArrayList<Object> user = new ObservableArrayList<>(); user.add("Google"); user.add("Inc."); user.add(17);
No layout, é possível acessar a lista pelos índices, conforme mostrado no exemplo a seguir:
<data>
<import type="android.databinding.ObservableList"/>
<import type="com.example.my.app.Fields"/>
<variable name="user" type="ObservableList<Object>"/>
</data>
…
<TextView
android:text='@{user[Fields.LAST_NAME]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Objetos observáveis
Uma classe que implementa a interface Observable
permite o registro de
listeners que querem ser notificados sobre mudanças de propriedade do objeto
observável.
A interface Observable
tem um mecanismo para adicionar e remover listeners, mas você
decide quando as notificações são enviadas. Para facilitar o desenvolvimento, a biblioteca Data
Binding fornece a classe
BaseObservable
, que
implementa o mecanismo de registro de listener. A classe de dados que implementa
BaseObservable
é responsável por notificar quando as propriedades mudam. Para fazer
isso, atribua uma anotação Bindable
ao getter e chame o método
notifyPropertyChanged()
no setter, conforme mostrado no exemplo a seguir.
Kotlin
class User : BaseObservable() { @get:Bindable var firstName: String = "" set(value) { field = value notifyPropertyChanged(BR.firstName) } @get:Bindable var lastName: String = "" set(value) { field = value notifyPropertyChanged(BR.lastName) } }
Java
private static class User extends BaseObservable { private String firstName; private String lastName; @Bindable public String getFirstName() { return this.firstName; } @Bindable public String getLastName() { return this.lastName; } public void setFirstName(String firstName) { this.firstName = firstName; notifyPropertyChanged(BR.firstName); } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); } }
A vinculação de dados gera uma classe chamada BR
no pacote do módulo, que contém
os IDs dos recursos usados para a vinculação de dados. A anotação Bindable
gera uma entrada no arquivo de classe BR
durante a compilação. Se não for possível mudar a classe base
das classes de dados, implemente a interface Observable
usando um objeto
PropertyChangeRegistry
para registrar e notificar os listeners de forma eficiente.
Objetos com reconhecimento de ciclo de vida
Os layouts do app também podem se vincular a fontes de vinculação de dados que notificam automaticamente a interface sobre mudanças nos dados. Dessa forma, as vinculações reconhecem o ciclo de vida e só são acionadas quando a interface está visível na tela.
A vinculação de dados oferece suporte a
StateFlow
e
LiveData
. Para saber mais sobre
o uso de LiveData
na vinculação de dados, consulte Usar LiveData para notificar a interface sobre mudanças
de dados.
Usar o StateFlow
Se o app usa o Kotlin com corrotinas, você pode usar objetos
StateFlow
como a fonte de vinculação de dados. Para usar um objeto StateFlow
com
sua classe de vinculação, especifique um proprietário do ciclo de vida para definir o escopo do
objeto StateFlow
. O exemplo a seguir especifica a atividade como a
proprietária do ciclo de vida após a classe de vinculação ser instanciada:
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Specify the current activity as the lifecycle owner.
binding.lifecycleOwner = this
}
}
Conforme descrito em Vincular visualizações de layout a componentes
de arquitetura, a vinculação de dados
funciona perfeitamente com objetos
ViewModel
. Você pode usar StateFlow
e ViewModel
juntos da seguinte maneira:
class ScheduleViewModel : ViewModel() {
private val _username = MutableStateFlow<String>("")
val username: StateFlow<String> = _username
init {
viewModelScope.launch {
_username.value = Repository.loadUserName()
}
}
}
No layout, atribua as propriedades e os métodos do objeto ViewModel
às
visualizações correspondentes usando expressões de vinculação, conforme mostrado no exemplo
a seguir:
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
A interface é atualizada automaticamente sempre que o valor do nome do usuário muda.
Desativar o suporte ao StateFlow
Para apps que usam o Kotlin e o AndroidX, o suporte ao StateFlow
é incluído automaticamente
na vinculação de dados. Isso significa que a dependência de corrotinas será
incluída automaticamente no app se ela ainda não estiver disponível.
Você pode desativar essa funcionalidade adicionando o seguinte ao seu
arquivo build.gradle
:
Groovy
android { ... dataBinding { addKtx = false } }
Kotlin
android { ... dataBinding { addKtx = false } }
Como alternativa, você pode desativar StateFlow
globalmente no seu projeto adicionando
a seguinte linha ao arquivo gradle.properties
:
Groovy
android.defaults.databinding.addKtx = false
Kotlin
android.defaults.databinding.addKtx = false
Outros recursos
Para saber mais sobre a vinculação de dados, consulte os recursos a seguir:
Exemplos
- Exemplos da biblioteca Android Data Binding (link em inglês)
Codelabs
Postagens do blog
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Módulo Saved State para ViewModel
- Vincular visualizações de layout a componentes de arquitetura
- Visão geral da biblioteca Paging