Jetpack

🔀【Jetpack】Android DataBinding 數據綁定 範例🔧

🔀【Jetpack】Android DataBinding 數據綁定 範例🔧

Android Databinding 是 Android 平台上提供的一個壓縮開發流程和提升可維護性的資料綁定機制,其主要功能為簡化 Android 對應用程序 UI 的數據繫結和資料流傳遞,例如將功能控件與資料模型中存儲的數據繫結在一起,使應用程序的最終用戶可以用一個相對簡潔的語法將功能控件的數據(屬性)與資料模型繫結在一起,符合低耦合和高可擴展性的原則,降低程序的開發、維護和測試的成本,提高開發的效率。


文章目錄

  1. DataBinding & Fragment KTX 導入
  2. DataBinding
  3. DataBinding StateFlow 配合 ViewModel 更新 UI
  4. DataBinding 自定義單參數屬性
  5. DataBinding 自定義多參數屬性
  6. DataBinding 導入 View 寫判斷
  7. Developer Documents DataBinding

1.DataBinding & Fragment KTX 導入

build.gradle
android {

    buildFeatures {
        dataBinding true
    }
}

dependencies {
    def fragment_version = "1.5.5"
    implementation "androidx.fragment:fragment-ktx:$fragment_version"
}

2.DataBinding

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="name"
            type="String" />

        <variable
            name="age"
            type="Integer" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@{name + '\n' + age}"
            android:textSize="50sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainActivity.kt
class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

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

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

        binding.name = "Wade"
        binding.age = 26
    }
}

3.DataBinding StateFlow 配合 ViewModel 更新 UI

PersonViewModel.kt
class PersonViewModel : ViewModel() {

    private val _name = MutableStateFlow("Fly")
    val name = _name.asStateFlow()

    private val _age = MutableStateFlow(20)
    val age = _age.asStateFlow()

    fun changeData() {
        viewModelScope.launch {
            _name.emit("Wade")
            _age.emit(26)
        }
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.example.jetpackdemo.PersonViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:onClick="@{() -> viewModel.changeData()}"
            android:text="@{viewModel.name + '\n' + viewModel.age}"
            android:textSize="50sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainActivity.kt
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val viewModel: PersonViewModel by viewModels()

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

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.viewModel = viewModel
        binding.lifecycleOwner = this

    }
}

4.DataBinding 自定義單參數屬性

build.gradle
plugins {
    id 'kotlin-kapt'
}
BindingAdapters
object BindingAdapters {

    @JvmStatic
    @BindingAdapter("app:hideIfZero")
    fun hideIfZero(view: View, name: String) {
        view.isVisible = name == "Wade"
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.example.jetpackdemo.PersonViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/appCompatTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:onClick="@{() -> viewModel.changeData()}"
            android:text="@{viewModel.name + '\n' + viewModel.age}"
            android:textSize="50sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hi"
            android:textSize="60sp"
            app:hideIfZero="@{viewModel.name}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/appCompatTextView" />

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

5.DataBinding 自定義多參數屬性

BindingAdapters
object BindingAdapters {

    @JvmStatic
    @BindingAdapter(value = ["app:realText", "app:realTextColor"], requireAll = true)
    fun setRealText(view: AppCompatTextView, text: String, color: String) {
        view.text = text
        view.setTextColor(Color.parseColor(color))
    }
}
PersonViewModel.kt
class PersonViewModel : ViewModel() {

    private val _name = MutableStateFlow("Fly")
    private val _age = MutableStateFlow(20)
    private val _hello = MutableStateFlow("Hi")
    private val _helloColor = MutableStateFlow("#FF0000")

    val name = _name.asStateFlow()
    val age = _age.asStateFlow()
    val hello = _hello.asStateFlow()
    val helloColor = _helloColor.asStateFlow()

    fun changeData() {
        viewModelScope.launch {
            _name.emit("Wade")
            _age.emit(26)
            _hello.emit("Hello")
            _helloColor.emit("#FF00FF")
        }
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.example.jetpackdemo.PersonViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/appCompatTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:onClick="@{() -> viewModel.changeData()}"
            android:text="@{viewModel.name + '\n' + viewModel.age}"
            android:textSize="50sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hi"
            android:textSize="60sp"
            app:realText="@{viewModel.hello}"
            app:realTextColor="@{viewModel.helloColor}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/appCompatTextView" />

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

6.DataBinding 導入 View 寫判斷

PersonViewModel
class PersonViewModel : ViewModel() {

    private val _name = MutableStateFlow("Fly")
    private val _age = MutableStateFlow(20)
    private val _nameVisible = MutableStateFlow(true)

    val name = _name.asStateFlow()
    val age = _age.asStateFlow()
    val nameVisible = _nameVisible.asStateFlow()


    fun changeData() {
        viewModelScope.launch {
            _name.emit("Wade")
            _age.emit(26)
            _nameVisible.emit(false)
        }
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View" alias="AndroidView"/>

        <variable
            name="viewModel"
            type="com.example.jetpackdemo.PersonViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/appCompatTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:onClick="@{() -> viewModel.changeData()}"
            android:text="@{viewModel.name + '\n' + viewModel.age}"
            android:textSize="50sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hi"
            android:textSize="60sp"
            android:visibility="@{viewModel.nameVisible ? AndroidView.VISIBLE : AndroidView.GONE }"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/appCompatTextView" />

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

7.Developer Documents DataBinding

Open in Documents DataBinding

發表迴響