Computer >> Máy Tính >  >> Hệ thống >> Android

Cách ràng buộc dữ liệu trong Android

Liên kết dữ liệu là một kỹ thuật được sử dụng khi bạn muốn kết dính các phần thông tin (dữ liệu của bạn) với một số yếu tố đầu vào trực quan của người dùng. Trong quá trình này, bất cứ khi nào đầu vào được cập nhật, dữ liệu đằng sau nó cũng được cập nhật.

Đây không phải là một khái niệm mới và có rất nhiều khuôn khổ đã kết hợp điều này vào thiết kế của họ (như AngularJS / React / Vue).

Sự chú ý của chúng tôi trong bài viết này không phải là các khuôn khổ front-end mà là sự phát triển trên thiết bị di động. Google đã giới thiệu Thư viện liên kết dữ liệu trong Android, là một phần của Android Jetpack.

Nếu bạn không quen với bộ thư viện Jetpack, có thể là do Google đã thông báo rằng họ sẽ ngừng phát triển các thư viện hỗ trợ của mình. Thay vào đó, nó sẽ chuyển sang hỗ trợ các thư viện AndroidX (là phiên bản mới hơn của các thư viện hỗ trợ).

Tôi biết rằng có nhiều bài viết giải thích cách sử dụng liên kết dữ liệu bằng bộ điều hợp, nhưng phần này sẽ không tập trung vào điều đó. Thay vào đó, tôi sẽ chỉ ra một cách tiếp cận đơn giản, tối thiểu để liên kết dữ liệu có thể giúp bạn tiết kiệm thời gian bằng cách giảm thiểu số lượng mã bạn phải viết.

Tại sao lại sử dụng Data Binding?

Nếu bạn chưa bán, hãy dành vài phút để giải thích lợi ích của việc sử dụng liên kết dữ liệu bằng cách hiển thị một ví dụ. Giả sử bạn có một menu với ba nút tùy chỉnh, trong đó mỗi nút là một bố cục bên trong.

Cách ràng buộc dữ liệu trong Android
Bố cục của chúng tôi

Một cách để tạo tất cả những điều này là sử dụng bốn bố cục XML khác nhau:một cho bố cục chính và một cho ba nút.

Bạn cần làm điều này vì mỗi nút sẽ hướng người dùng đến một phần khác nhau trong ứng dụng của bạn và do đó cần văn bản khác nhau và hình ảnh khác.

<?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>
Bố cục của một nút

Đúng là, đây không phải là quá nhiều trùng lặp mã vì chúng tôi chỉ xử lý ba bố cục. Nhưng nếu bạn nghĩ về nó, sẽ khá lãng phí thời gian để xử lý tất cả mã đó. Nếu bạn tính đến một ứng dụng có bố cục phức tạp hơn, một ứng dụng có thể giới thiệu các sản phẩm và hình ảnh của chúng, thì điều này có thể dẫn đến nhiều lần sao chép mã tẻ nhạt.

Với liên kết dữ liệu, chúng tôi sẽ quản lý để chỉ tạo một bố cục XML sẽ được sử dụng bởi tất cả các nút của chúng tôi.

Chúng ta bắt đầu từ đâu?

Chúng ta cần cho phép dự án của mình kích hoạt tính năng ràng buộc dữ liệu. Để làm được điều đó, chúng ta cần thêm dataBinding phần tử trong build.gradle của ứng dụng của chúng tôi tệp:

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

Sau khi đồng bộ hóa dự án của mình, chúng tôi sẽ tạo lớp dữ liệu của mình, lớp này sẽ sử dụng để liên kết bố cục.

package com.tomerpacific.example

import android.graphics.drawable.Drawable

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

Hãy chú ý đến thực tế là chúng ta có hai trường trong ButtonData lớp:

  • buttonText - Đây là văn bản sẽ hiển thị bên dưới hình ảnh của chúng tôi.
  • buttonImageSrc - Điều này chịu trách nhiệm về hình ảnh của nút.

Nếu chúng tôi muốn có thêm dữ liệu, chúng tôi sẽ chỉ thêm nhiều trường hơn vào lớp dữ liệu của mình.

Ràng buộc Thực tế

Tiếp theo, chúng ta cần khai báo một thuộc tính biến trong layout của chúng ta để nó có thể được sử dụng. Biến này sẽ được liên kết với lớp dữ liệu mà chúng ta đã tạo. Để làm được điều này, có hai điều chúng ta cần làm:

  • Gói phần tử bố cục gốc của chúng tôi trong thẻ bố cục.
  • Thêm thẻ dữ liệu sẽ chứa khai báo biến của chúng tôi (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

Lưu ý rằng chúng ta có thể xóa lược đồ khỏi bố cục chính trước đó khi nó được chuyển đến thẻ bố cục gốc. Ngoài ra, biến chúng tôi đã thêm được gắn trực tiếp với lớp dữ liệu của chúng tôi.

Trong MainActivity của chúng tôi tệp, chúng tôi cần thêm mã để xử lý ràng buộc:

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

Mỗi khi bạn tạo một biến bên trong một bố cục, một lớp liên kết sẽ được tạo tự động cho bố cục đó. Trong trường hợp của chúng tôi, bố cục của chúng tôi được gọi là activity_main , vì vậy lớp liên kết sẽ được đặt tên là ActivityMainBinding .

Quy ước luôn là tên của bố cục có Ràng buộc được thêm vào cuối.

Vì chúng tôi đã khai báo buttonData là biến của chúng tôi trong bố cục, nó được nối vào đối tượng liên kết và chúng tôi có thể gán cho nó một phiên bản mới của ButtonData của chúng tôi lớp học.

Sau khi làm tất cả những điều đó, cuối cùng chúng ta có thể sử dụng dữ liệu mà chúng ta vừa ràng buộc trong bố cục của mình.

<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" />
Sử dụng nút Biến được ràng buộc Dữ liệu

Và kết quả là:

Cách ràng buộc dữ liệu trong Android
Khá mượt phải không?

Chờ một chút…

Chúng tôi có ba nút và lớp dữ liệu của chúng tôi chỉ có thể được sử dụng cho một nút, vậy làm cách nào để vượt qua điều này?

package com.tomerpacific.example

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

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

Chúng tôi đã phải ghi đè get vì nó cần được công nhận khi chúng ta sử dụng nó trong bố cục của mình.

Sau đó, chúng tôi cần thay đổi các tham chiếu trong activity_main.xml của chúng tôi :

 <data>
        <variable name="buttonsData" type="com.tomerpacific.example.ButtonsData"/>
 </data>
Chúng tôi đã thay đổi tên biến và lớp để phù hợp với ButtonsData

Và chúng ta phải tạo một ràng buộc mới cho lớp dữ liệu mới:

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

Chúng tôi tạo ba phiên bản của ButtonData lớp. Sau đó, chúng tôi khởi tạo một ButtonsData và đính kèm nó vào đối tượng ràng buộc của chúng tôi.

Cuối cùng, bây giờ chúng ta có thể sử dụng đúng lớp dữ liệu trong bố cục của mình:

 <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>
Ví dụ về cách sử dụng một phần tử
Cách ràng buộc dữ liệu trong Android
Hoạt động như một sự quyến rũ

Bài viết này được viết do kinh nghiệm của tôi khi phát triển ứng dụng sau:

(Bạn chưa bao giờ biết, nó có thể hữu ích)

Ký hiệu đồ giặt - Ứng dụng trên Google Play Chà, bạn thật may mắn! Ứng dụng này có giải thích về tất cả những biểu tượng trông kỳ lạ đó với giao diện và hình ảnh dễ sử dụng Cách ràng buộc dữ liệu trong Android tomerpacificApps trên Google Play Cách ràng buộc dữ liệu trong Android
Tải qua Cửa hàng Google Play

Bạn có thể xem toàn bộ mã nguồn tại đây:

TomerPacific / LaundrySymbols Một ứng dụng được viết bằng Kotlin hiển thị các ký hiệu giặt khác nhau kèm theo giải thích:lốc xoáy:- TomerPacific / LaundrySymbols Cách ràng buộc dữ liệu trong Android TomerPacificGitHub Cách ràng buộc dữ liệu trong Android
Xem toàn bộ mã nguồn