Trabalhar com objetos de dados observáveis

Observabilidade é a capacidade de um objeto de notificar outros sobre alterações nos dados. A Data Binding Library permite que você faça objetos, campos ou as coleções observáveis.

Você pode usar qualquer objeto para vinculação de dados, mas a modificação não atualizar a IU automaticamente. Você pode usar a vinculação de dados para fornecer aos seus dados a capacidade de notificar outros objetos (conhecidos como listeners) quando as mudanças nos dados. Há três tipos de classes observáveis: campos, coleções e objetos.

Quando um desses objetos de dados observáveis é vinculado à IU e uma propriedade do quando o objeto de dados mudar, a interface será atualizada automaticamente.

Campos observáveis

Caso suas classes tenham apenas algumas propriedades, pode não valer a pena o esforço de crie classes que implementem a Observable. Neste caso, é possível usar a classe Observable genérica e os seguintes Classes específicas de primitivos para tornar os campos observáveis:

Campos observáveis são objetos observáveis independentes que têm uma única . As versões primitivas evitam encaixotar e desencaixar a caixa durante o acesso. as operações. Para usar esse mecanismo, crie uma propriedade public final na biblioteca ou uma propriedade somente leitura em Kotlin, como mostrado nas exemplo a seguir:

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 o set() e Métodos do acessador get() ou use a propriedade do Kotlin sintaxe:

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 acesso a essas estruturas usando uma chave. A Classe ObservableArrayMap é útil quando a chave é um tipo de referência, como String, conforme mostrado 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ê pode encontrar o mapa usando as chaves de string, conforme mostrado no exemplo a seguir:

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap&lt;String, Object&gt;"/>
</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"/>

O ObservableArrayList é útil quando a chave é um número inteiro, da seguinte maneira:

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&lt;Object&gt;"/>
</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 da ouvintes que querem ser notificados sobre mudanças de propriedade dos dados observáveis objeto.

A interface Observable tem um mecanismo para adicionar e remover listeners, mas é decide quando as notificações são enviadas. Para facilitar o desenvolvimento, o módulo A Binding Library fornece a classe BaseObservable, que implementa o mecanismo de registro do listener. A classe de dados que implementa BaseObservable é responsável por notificar quando as propriedades mudam. Afazeres atribua uma anotação Bindable para o getter e chamar 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 vinculação de dados. A anotação Bindable gera uma entrada no arquivo da classe BR durante a compilação. Se a classe de base para classes de dados não possa ser mudado, implemente a interface Observable usando um PropertyChangeRegistry para registrar e notificar os listeners de forma eficiente.

Objetos com reconhecimento de ciclo de vida

Os layouts do seu app também podem se vincular a fontes de vinculação de dados que automaticamente notificar a interface sobre alterações nos dados. Dessa forma, suas vinculações reconhecem o ciclo de vida e são acionados somente quando a interface está visível na tela.

A vinculação de dados oferece suporte StateFlow e LiveData Para mais informações sobre usando LiveData na vinculação de dados, consulte Usar o LiveData para notificar a interface sobre os dados mudanças.

Usar StateFlow

Se o app usa o Kotlin com corrotinas, você pode usar StateFlow como 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 da StateFlow. O exemplo a seguir especifica a atividade como proprietário 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 à arquitetura componentes, vinculação de dados funciona perfeitamente com ViewModel objetos. É possível 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 a as visualizações correspondentes usando expressões de vinculação, conforme mostrado abaixo exemplo:

<TextView
    android:id="@+id/name"
    android:text="@{viewmodel.username}" />

A IU é atualizada automaticamente sempre que o valor do nome do usuário muda.

Desativar o suporte ao StateFlow

Para apps que usam Kotlin e AndroidX, o suporte a StateFlow é automaticamente incluídos na vinculação de dados. Isso significa que a dependência de corrotinas é incluída automaticamente no app se a dependência ainda não estiver disponível.

Para desativar essa funcionalidade, adicione o seguinte ao seu Arquivo build.gradle:

Groovy

android {
    ...
    dataBinding {
        addKtx = false
    }
}

Kotlin

android {
    ...
    dataBinding {
        addKtx = false
    }
}

Como alternativa, é possível desativar StateFlow globalmente no projeto adicionando linha a seguir ao arquivo gradle.properties:

Groovy

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

Outros recursos

Para saber mais sobre vinculação de dados, consulte os recursos a seguir:

Amostras

Codelabs

Postagens do blog