Android
 Computer >> コンピューター >  >> システム >> Android

Android でデータをバインドする方法

データ バインディングは、視覚的なユーザー入力要素に情報 (データ) を接着するときに使用する手法です。このプロセスでは、入力が更新されるたびに、その背後にあるデータも更新されます。

これは決して新しい概念ではなく、これを設計に組み込んだフレームワークが多数あります (AngularJS/React/Vue など)。

この記事で注目するのは、フロントエンド フレームワークではなく、モバイル開発です。 Google は、Android Jetpack の一部である Data Binding Library を Android に導入しました。

Jetpack ライブラリ スイートに慣れていない場合は、Google がサポート ライブラリの開発を中止すると発表したことが原因である可能性があります。代わりに、サポートする AndroidX ライブラリ (サポート ライブラリの新しいバージョン) に移動します。

アダプターを使用してデータ バインディングを使用する方法を説明する記事が多数あることは承知していますが、この記事ではその点に焦点を当てません。代わりに、記述する必要のあるコードの量を最小限に抑えることで時間を節約できる、データ バインディングへの最低限の最小限のアプローチを示します。

データ バインディングを使用する理由

まだ納得していない場合は、例を示してデータ バインディングを使用する利点を説明します。 3 つのカスタム ボタンを含むメニューがあり、各ボタンがそれ自体のレイアウトになっているとします。

Android でデータをバインドする方法
レイアウト

これらすべてを生成する 1 つの方法は、4 つの異なる XML レイアウトを使用することです。1 つはメイン レイアウト用で、もう 1 つは 3 つのボタンのそれぞれです。

各ボタンはユーザーをアプリケーションの異なる部分に誘導するため、異なるテキストと異なる画像が必要になるため、これを行う必要があります。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_gravity="center_horizontal"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content">


    <ImageView
        android:id="@+id/imageView"
        android:layout_height="100dp"
        android:layout_width="100dp"
        android:src="@drawable/image_name"
        android:adjustViewBounds="true"
        android:scaleType="centerInside"
        />

    <TextView
        android:id="@+id/textView"
        android:gravity="center_horizontal"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="Image Text"
        android:textSize="16sp" />

</LinearLayout>
ボタンのレイアウト

確かに、3 つのレイアウトしか扱っていないため、これは多くのコードの重複ではありません。しかし、よく考えてみると、そのすべてのコードを処理するのは時間の無駄です。より複雑なレイアウトを持つアプリケーション (製品とその画像を表示するアプリケーション) を考慮すると、多くの面倒なコードの複製につながる可能性があります。

データ バインディングを使用すると、すべてのボタンで使用される XML レイアウトを 1 つだけ作成できます。

どこから始めますか?

プロジェクトでデータバインディングを有効にする必要があります。そのためには、 dataBinding を追加する必要があります アプリケーションの build.gradle の要素 ファイル:

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.tomerpacific.example"
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        dataBinding {              //<-------
          enabled = true
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
build.gradle

プロジェクトを同期した後、レイアウトをバインドするために使用するデータ クラスを作成します。

package com.tomerpacific.example

import android.graphics.drawable.Drawable

data class ButtonData(val buttonText: String, val buttonImageSrc : Drawable)
ButtonData.kt

ButtonData に 2 つのフィールドがあることに注意してください。 クラス:

  • buttonText — これは、画像の下に表示されるテキストです。
  • buttonImageSrc — これはボタンの画像を担当します。

さらにデータが必要な場合は、データ クラスにフィールドを追加するだけです。

実際のバインディング

次に、使用できるように、レイアウトで変数プロパティを宣言する必要があります。この変数は、作成したデータ クラスにバインドされます。これを行うには、次の 2 つのことを行う必要があります:

  • ルート レイアウト要素をレイアウト タグでラップします。
  • 変数の宣言を含むデータ タグを追加します (buttonData ).
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android">  // <---- 1
                                                                              
    <data>
        <variable name="buttonData" type="com.tomerpacific.example.ButtonData"/> // <---- 2
    </data>
    
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:app="https://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Example"
            android:textSize="30dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:orientation="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/linearLayout3"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView2">

            <ImageButton
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:adjustViewBounds="true"
                android:scaleType="centerInside"
                android:src="@drawable/android">

            </ImageButton>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="Image Text"
                android:textSize="16sp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:orientation="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView2"
            app:layout_constraintVertical_bias="0.504">

            <ImageButton
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:adjustViewBounds="true"
                android:scaleType="centerInside"
                android:src="@drawable/android_p_logo">

            </ImageButton>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="Image Text"
                android:textSize="16sp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:orientation="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.200"
            app:layout_constraintStart_toEndOf="@+id/linearLayout3"
            app:layout_constraintTop_toBottomOf="@+id/textView2"
            app:layout_constraintVertical_bias="0.504">

            <ImageButton
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:adjustViewBounds="true"
                android:scaleType="centerInside"
                android:src="@drawable/android_studio_icon">

            </ImageButton>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="Image Text"
                android:textSize="16sp" />

        </LinearLayout>


    </androidx.constraintlayout.widget.ConstraintLayout>
    
</layout>
activity_main.xml

ルート レイアウト タグに移動したため、以前のメイン レイアウトからスキーマを削除できることに注意してください。また、追加した変数はデータ クラスに直接関連付けられています。

MainActivity では ファイルでは、バインディングを処理するコードを追加する必要があります:

package com.tomerpacific.example

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.tomerpacific.example.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val binding: ActivityMainBinding = DataBindingUtil.setContentView(
            this, R.layout.activity_main)

        binding.buttonData = ButtonData("First", resources.getDrawable(R.drawable.android))
    }
}
MainActivity.kt

レイアウト内に変数を作成するたびに、そのレイアウトのバインディング クラスが自動的に生成されます。この場合、レイアウトは activity_main と呼ばれます であるため、バインディング クラスの名前は ActivityMainBinding になります。 .

規則は常に Binding を使用したレイアウトの名前です 最後に追加。

buttonData を宣言したので レイアウトの変数として、バインディング オブジェクトに追加され、ButtonData の新しいインスタンスを割り当てることができます。 クラス。

以上のことをすべて行った後、レイアウトでバインドしたデータを最終的に使用できます。

<LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:orientation="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/linearLayout3"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView2">

            <ImageButton
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:adjustViewBounds="true"
                android:scaleType="centerInside"
                android:src="@{buttonData.buttonImageSrc}">  // <----

            </ImageButton>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="@{buttonData.buttonText}"   // <----
                android:textSize="16sp" />
バインドされた変数 buttonData の使用

結果は次のとおりです。

Android でデータをバインドする方法
かなりスムーズですね?

ちょっと待って…

3 つのボタンがあり、データ クラスは 1 つのボタンにしか使用できないので、どうすればこれを乗り越えられるでしょうか?

package com.tomerpacific.example

data class ButtonsData(val buttonsData : List<ButtonData>) {

    fun get(index: Int) : ButtonData {
        return buttonsData.get(index)
    }
}
ButtonsData.kt

get をオーバーライドする必要がありました レイアウトで使用するときに認識される必要があるためです。

次に、activity_main.xml の参照を変更する必要があります。 :

 <data>
        <variable name="buttonsData" type="com.tomerpacific.example.ButtonsData"/>
 </data>
ButtonsData に合わせて変数名とクラスを変更しました

そして、新しいデータ クラスへの新しいバインディングを作成する必要があります:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val binding: ActivityMainBinding = DataBindingUtil.setContentView(
            this, R.layout.activity_main)

        val firstButton : ButtonData = ButtonData("First", resources.getDrawable(R.drawable.android))

        val secondButton : ButtonData = ButtonData("Second", resources.getDrawable(R.drawable.android_p_logo))

        val thirdButton : ButtonData = ButtonData("Third", resources.getDrawable(R.drawable.android_studio_icon))

        val buttonsData : ButtonsData = ButtonsData(listOf(firstButton, secondButton, thirdButton))

        binding.buttonsData = buttonsData
    }
MainActivity.kt

ButtonData の 3 つのインスタンスを作成します クラス。次に ButtonsData をインスタンス化します オブジェクトを結合オブジェクトにアタッチします。

最後に、レイアウトでデータ クラスを適切に使用できるようになりました。

 <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:orientation="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/linearLayout3"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView2">

            <ImageButton
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:adjustViewBounds="true"
                android:scaleType="centerInside"
                android:src="@{buttonsData.get(0).buttonImageSrc}">   // <-------

            </ImageButton>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="@{buttonsData.get(0).buttonText}"       // <--------
                android:textSize="16sp" />

        </LinearLayout>
1 つの要素の使用例
Android でデータをバインドする方法
魅力的な働き

この記事は、次のアプリケーションを開発した経験から書かれました:

(あなたは決して知りません、それは役に立つかもしれません)

ランドリー シンボル - Google Play のアプリ ランドリー シンボルの意味を理解するのに苦労したことはありませんか?運がいいですね!このアプリには、使いやすいインターフェイスと写真を使用して、すべての奇妙に見える記号の説明が含まれています Android でデータをバインドする方法 Google Play の tomerpacificApps Android でデータをバインドする方法
Google Play ストアから入手

ここでソースコード全体を見ることができます:

TomerPacific/LaundrySymbolsKotlin で記述されたアプリケーションで、さまざまな洗濯記号を説明付きで表示します:cyclone:- TomerPacific/LaundrySymbols Android でデータをバインドする方法 TomerPacificGitHub Android でデータをバインドする方法
完全なソースコードを見る

  1. Android でデータ使用量を超えないようにする方法

    インターネットはスマートフォンの生命線であり、残念ながら無料ではありません。 ISP によってさまざまなプランが提供されており、国によっても異なります。世界中で普遍的に無料の Wi-Fi を利用する前に、Check Data Usage のようなモバイル データ セーバー アプリを使用して、Android スマートフォンで過剰なデータ使用量を回避する必要があります。 Systweak によって開発されたこのアプリは、ユーザーがモバイル データと Wi-Fi を使用してインターネット データの使用状況を監視し、帯域幅の速度をリアルタイムで確認するのに役立ちます。 データ使用量の確認:Androi

  2. Android でのモバイル データの問題を修正する方法

    初めてスマートフォンを手に入れたとき、セルラー データまたはモバイル データは、生活に必要なものの 1 つです。 Google マップがなければどこに行くのか、Flipboard がなければ何を読めばよいのか、WhatsApp がなければ人々に連絡する方法がわからないことに気付くのは、接続が失われるまでです。この記事では、モバイル データの問題を解決してオンラインに戻すための効率的な方法を紹介します。 Android でのモバイル データの問題を修正する方法 APN設定をリセット すべてのモバイル ネットワーク オペレータは、アクセス ポイント名 (APN) を使用して携帯電話をモバイル イ