iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 26
0
Mobile Development

大一之 Android Kotlin 自習心路歷程系列 第 26

[Day 26] Android in Kotlin: Data Binding 簡單示範

Data binding 強化了 XML 在 project 裡的功能和地位,讓元件可以在 XML 就綁上點擊事件、資料等等。

在開始進行 data binding 以前,要先設定環境。
首先是在 Gradle(Module:app)加上以下

apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
    buildFeatures {
        dataBinding true
    }
}
dependencies {
    kapt "com.android.databinding:compiler:3.1.4"
}

跟 Gradle(Project: ProjectName)

buildscript {
    ext.kotlin_version = "1.4.10"
    dependencies {
        classpath "com.android.tools.build:gradle:4.0.2"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

在 data binding 時,會跟 view model 有比較大的關連,所以先講 view model。

ViewModel

這次我的資料只有放在 view model 裡面了。

class MainViewModel: ViewModel(){

    var data= ObservableField<String>("")

    init {
        data.set("init")
    }

    fun btnClick(){
        data.set("clicked!")
    }
}

裡面有一個資料跟方法
Observable 是給 view model 用的型態,跟之前講的 live data 有點類似,可以用 getter and setter 取值給值。

XML

一個 text view 一個 edit view 一個 button

data binding 要在最外面加上 layout 包起來,記得把 xmlns 的屬性也移進去。

<?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.mvvm.ui.main.MainViewModel"/>
    </data>

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainActivity">
    
     <TextView
        android:id="@+id/textMainResult"
        android:text="@{viewModel.data}"
        android:textSize="30sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@id/editMain"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
        
    <EditText
        android:id="@+id/editMain"
        android:gravity="center"
        android:text="@={viewModel.data}"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintVertical_bias="0.3" />
        
    <Button
        android:id="@+id/btnMainResult"
        android:text="result"
        android:onClick="@{() -> viewModel.btnClick()}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/editMain"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintVertical_bias="0.2"/>

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

可以發現除了外面的 layout 以外,跟一般的 XML 前面還多了 data 的標籤。那是 XML 的資料來源,通常會丟 view model 近來,這樣就可以把 view model 裡的東西丟給各元件了。

從 text view 的 text 屬性可以看到,他是利用"@{viewmodel.你要的ObservableField成員}" 進行 data binding。

如果想要可以改變 binding 的值,要在 @ 跟 { } 之間加上等號,這樣就代表可以雙向改變此資料,例如 edit text,在打入字的時候,data 也會跟著改變。

按鈕則可以在 onClick 屬性加上方法,套用上 "@{() -> 你要的方法}"

Activity

class MainActivity : AppCompatActivity() {

    private val viewModel: MainViewModel by lazy {
        ViewModelProvider(this, MyViewModelFactory()).get(MainViewModel::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        
        // binding.viewModel 是 XML <data> 裡的那個
        binding.viewModel = viewModel
    }
}

個人覺得 data binding 最舒服的地方就是 activity 不用再加上一大堆的 findViewById。

只要加上 binding 跟 設置 viewModel。

中間的 ActivityMainBinding 不是我宣告的,做好以後 build 成功會自動出現。

成果

打入 edit text

按下按鈕

在最後寫個筆者認為的 data binding 的缺點,就是不方便 debug。
每次有地方寫錯,它只會跟你說 ActivityMainBindingImpl 出錯誤了,留下一模一樣的東西,實在是有點難搞。
筆者之後就都還是做成 LiveData 了 :|


上一篇
[Day 25] Android in Kotlin: Room Database 操作示範
下一篇
[Day 27] Android in Kotlin: RecyclerView 和 ViewPager2 實作分享
系列文
大一之 Android Kotlin 自習心路歷程30

尚未有邦友留言

立即登入留言