A biblioteca AndroidX inclui os Componentes da arquitetura, que podem ser usados para criar apps robustos, testáveis e de fácil manutenção. A biblioteca de vinculação de dados funciona perfeitamente com os componentes da arquitetura para simplificar ainda mais o desenvolvimento da interface. Os layouts do app podem ser vinculados aos dados nos componentes de arquitetura, que ajudam a gerenciar o ciclo de vida do controlador de IU e notificar a IU sobre mudanças nos dados.
Neste documento, mostramos como incorporar os componentes da arquitetura ao seu app para aproveitar ao máximo a biblioteca de vinculação de dados.
Usar LiveData para notificar a IU sobre mudanças de dados
Você pode usar objetos LiveData como a fonte de vinculação de dados para notificar automaticamente
a interface sobre mudanças nos dados. Para mais informações sobre esse
componente da arquitetura, consulte a visão geral do LiveData.
Ao contrário dos objetos que implementam Observable, como
campos observáveis, os objetos LiveData conhecem o ciclo de vida dos
observadores inscritos nas mudanças de dados. Esse conhecimento oferece muitos benefícios,
que são explicados em As vantagens de usar o LiveData. No Android Studio
versão 3.1 e mais recentes, é possível substituir campos observáveis por objetos LiveData
no código de vinculação de dados.
Para usar um objeto LiveData com sua classe de vinculação, é preciso especificar um
proprietário do ciclo de vida para definir o escopo do objeto LiveData. O exemplo
a seguir especifica a atividade como o proprietário do ciclo de vida depois que a classe de vinculação
é instanciada:
Kotlin
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.setLifecycleOwner(this)
}
}
Java
class ViewModelActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Inflate view and obtain an instance of the binding class.
UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);
// Specify the current activity as the lifecycle owner.
binding.setLifecycleOwner(this);
}
}
É possível usar um componente ViewModel, conforme explicado na seção a seguir,
para vincular os dados ao layout. No componente ViewModel, use o objeto
LiveData para transformar os dados ou mesclar várias fontes de dados. O
exemplo abaixo mostra como transformar os dados no ViewModel:
Kotlin
class ScheduleViewModel : ViewModel() {
val userName: LiveData<String>
init {
val result = Repository.userName
userName = Transformations.map(result) { result -> result.value }
}
}
Java
class ScheduleViewModel extends ViewModel {
LiveData<String> username;
public ScheduleViewModel() {
String result = Repository.userName;
userName = Transformations.map(result, result -> result.value);
}
}
Usar o ViewModel para gerenciar dados relacionados à IU
A biblioteca de vinculação de dados funciona perfeitamente com os componentes ViewModel. O
ViewModel expõe os dados que o layout observa e reage às mudanças.
O uso de componentes ViewModel com a biblioteca de vinculação de dados permite mover a lógica da interface
dos layouts para os componentes, que são mais fáceis de testar. A
biblioteca de vinculação de dados garante que as visualizações sejam vinculadas e desvinculadas da fonte de dados
quando necessário. A maior parte do trabalho restante consiste em garantir que
você está expondo os dados corretos. Para mais informações sobre esse componente de arquitetura, consulte a visão geral do ViewModel.
Para usar o componente ViewModel com a biblioteca de vinculação de dados, é preciso
instanciar o componente, que herda da classe ViewModel,
receber uma instância da classe de vinculação e atribuir o componente ViewModel
a uma propriedade na classe de vinculação. O exemplo a seguir mostra como usar o
componente com a biblioteca:
Kotlin
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Obtain the ViewModel component.
val userModel: UserModel by viewModels()
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Assign the component to a property in the binding class.
binding.viewmodel = userModel
}
}
Java
class ViewModelActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Obtain the ViewModel component.
UserModel userModel = new ViewModelProvider(this).get(UserModel.class);
// Inflate view and obtain an instance of the binding class.
UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);
// Assign the component to a property in the binding class.
binding.viewmodel = userModel;
}
}
No layout, atribua as propriedades e os métodos do componente ViewModel
às visualizações correspondentes que usam expressões de vinculação, conforme mostrado no
exemplo a seguir:
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@{viewmodel.rememberMe}"
android:onCheckedChanged="@{() -> viewmodel.rememberMeChanged()}" />
Usar um ViewModel observável para ter mais controle sobre os adaptadores de vinculação
É possível usar um componente ViewModel que implementa a interface Observable
para notificar outros componentes do app sobre mudanças nos dados, de forma semelhante
ao uso de um objeto LiveData.
Há situações em que você pode preferir usar um
componente ViewModel que implemente a interface
Observable em vez de usar objetos LiveData, mesmo que perca os recursos de gerenciamento
do ciclo de vida de LiveData. O uso de um componente ViewModel que
implementa Observable oferece mais controle sobre os adaptadores de vinculação no seu
app. Por exemplo, esse padrão oferece mais controle sobre as notificações
quando os dados mudam. Ele também permite especificar um método personalizado para definir o
valor de um atributo na vinculação de dados bidirecional.
Para implementar um componente ViewModel observável, crie uma classe que
herde da classe ViewModel e implemente a interface
Observable. É possível fornecer uma lógica personalizada quando um observador se inscreve ou
cancela a inscrição em notificações usando os métodos addOnPropertyChangedCallback()
e removeOnPropertyChangedCallback(). Também é possível fornecer
uma lógica personalizada que é executada quando as propriedades mudam no
método notifyPropertyChanged(). O exemplo de código abaixo mostra como
implementar um ViewModel observável:
Kotlin
/**
* A ViewModel that is also an Observable,
* to be used with the Data Binding Library.
*/
open class ObservableViewModel : ViewModel(), Observable {
private val callbacks: PropertyChangeRegistry = PropertyChangeRegistry()
override fun addOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.add(callback)
}
override fun removeOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.remove(callback)
}
/**
* Notifies observers that all properties of this instance have changed.
*/
fun notifyChange() {
callbacks.notifyCallbacks(this, 0, null)
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes must be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
fun notifyPropertyChanged(fieldId: Int) {
callbacks.notifyCallbacks(this, fieldId, null)
}
}
Java
/**
* A ViewModel that is also an Observable,
* to be used with the Data Binding Library.
*/
class ObservableViewModel extends ViewModel implements Observable {
private PropertyChangeRegistry callbacks = new PropertyChangeRegistry();
@Override
protected void addOnPropertyChangedCallback(
Observable.OnPropertyChangedCallback callback) {
callbacks.add(callback);
}
@Override
protected void removeOnPropertyChangedCallback(
Observable.OnPropertyChangedCallback callback) {
callbacks.remove(callback);
}
/**
* Notifies observers that all properties of this instance have changed.
*/
void notifyChange() {
callbacks.notifyCallbacks(this, 0, null);
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes must be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
void notifyPropertyChanged(int fieldId) {
callbacks.notifyCallbacks(this, fieldId, null);
}
}
Outros recursos
Para saber mais sobre a vinculação de dados, consulte os seguintes recursos adicionais.
- Amostras da Android Data Binding Library (link em inglês)
- Vinculação de dados: lições aprendidas (link em inglês)
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Trabalhar com objetos de dados observáveis
- Carregar e exibir dados paginados
- Usar corrotinas do Kotlin com componentes que reconhecem o ciclo de vida