監視可能なデータ オブジェクトを操作する

オブザーバビリティとは、オブジェクトが データを変更できます。データ バインディング ライブラリを使用すると、 コレクションのオブジェクトです。

データ バインディングには任意のオブジェクトを使用できるが、オブジェクトを変更しても UI が更新されます。データ バインディングを使用すると、データに 他のオブジェクト(リスナー)に、通知を送信したときに 制御できるようになります。監視可能なクラスには次の 3 種類があります。 フィールドコレクションオブジェクト

監視可能なデータ オブジェクトのいずれかが UI と データ オブジェクトが変更されると、UI が自動的に更新されます。

監視可能なフィールド

クラスのプロパティが数件しかない場合、 実装するクラスを作成する Observable インターフェース。この 汎用の Observable クラスと、 プリミティブ固有のクラスを使用して、フィールドを監視できるようにします。

監視可能フィールドは、自己完結型の監視可能なオブジェクトで、 表示されます。プリミティブ バージョンでは、アクセス中のボックス化とボックス化解除を回避できる 必要があります。このメカニズムを使用するには、Java で public final プロパティを作成します。 または読み取り専用のプロパティを使用します。 次の例をご覧ください。

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();
}

フィールドの値にアクセスするには、 set()get() アクセサ メソッド または、Kotlin プロパティを使用 構文:

Kotlin

user.firstName = "Google"
val age = user.age

Java

user.firstName.set("Google");
int age = user.age.get();

監視可能なコレクション

アプリによっては、データを保持するために動的な構造を使用することがあります。監視可能なコレクションを使用すると キーを使用してこれらの構造にアクセスできるようにします。「 ObservableArrayMap クラス が有用であるのは、キーが String などの参照型である場合です。 次の例をご覧ください。

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);

レイアウトでは、 次の例をご覧ください。

<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"/>

ObservableArrayList クラスは、次のようにキーが整数の場合に役立ちます。

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);

このレイアウトでは、 次の例をご覧ください。

<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"/>

監視可能なオブジェクト

Observable インターフェースを実装するクラスを使用すると、 プロパティの変更について通知を受け取りたいリスナー。 渡されます。

Observable インターフェースにはリスナーを追加および削除するメカニズムがありますが、 通知を送信するタイミングを指定できます。開発を容易にするために、Data API は バインディング ライブラリは、 BaseObservable クラスは、 リスナー登録メカニズムを実装します。実装するデータクラスは、 BaseObservable は、プロパティが変更されたときに通知します。タスク Bindable アノテーションを ゲッターに送り、 notifyPropertyChanged() メソッドに追加します。

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);
    }
}

データ バインディングは、モジュール パッケージ内に BR という名前のクラスを生成します。このクラスには、 データ バインディングに使用されるリソースの ID。Bindable アノテーション コンパイル時に、BR クラスファイルにエントリを生成します。基本クラスが データクラスでは変更できないため、Observable インターフェースを実装できます。 使用 PropertyChangeRegistry リスナーの登録と通知を効率的に行うことができます。

ライフサイクル対応オブジェクト

アプリのレイアウトは、データ バインディング ソースに自動的にバインドされ、 データの変更を UI に通知します。これにより、バインディングが UI が画面に表示されたときにのみトリガーされます。

データ バインディングのサポート StateFlowLiveData。詳細については、このモジュールの データ バインディングで LiveData を使用する方法については、LiveData を使用して UI にデータを通知するをご覧ください。 あります。

StateFlow を使用する

アプリで Kotlin とコルーチンを使用する場合は、次を使用できます。 データ バインディング ソースとして StateFlow オブジェクトを指定します。StateFlow オブジェクトを次の環境で使用する場合: ライフサイクル オーナーを指定して、スコープのスコープを StateFlow オブジェクト。次の例では、アクティビティを バインディング クラスがインスタンス化された後のライフサイクル オーナーに保持されます。

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
    }
}

レイアウト ビューをアーキテクチャにバインドする コンポーネント、データ バインディング ViewModel とシームレスに連携 説明します。次のように StateFlowViewModel を組み合わせて使用できます。

class ScheduleViewModel : ViewModel() {

    private val _username = MutableStateFlow<String>("")
    val username: StateFlow<String> = _username

    init {
        viewModelScope.launch {
            _username.value = Repository.loadUserName()
        }
    }
}

レイアウト内で、ViewModel オブジェクトのプロパティとメソッドを 対応するビューを、以下のようにバインディング式を使用して 例:

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

ユーザー名の値が変更されるたびに、UI が自動的に更新されます。

StateFlow サポートを無効にする

Kotlin と AndroidX を使用するアプリでは、StateFlow のサポートが自動的に有効になります。 データ バインディングに含まれるデータです。つまり、コルーチンの依存関係は 自動的にアプリに追加されます。

この機能を無効にするには、次のコードを build.gradle ファイル:

Groovy

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

Kotlin

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

または、次を追加して、プロジェクトで StateFlow をグローバルに無効にすることもできます。 次の行を gradle.properties ファイルに追加します。

Groovy

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

参考情報

データ バインディングについて詳しくは、以下の参考情報をご覧ください。

サンプル

Codelab

ブログ投稿