秒懂Android開發之DataBinding詳解 (part 1)

【版權申明】非商業目的註明出處可自由轉載
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/106267286
出自:shusheng007

概述

DataBinding 最早應該是在2015年末的時候就被提出了,那我爲什麼現在才寫一些相關的文章呢?因爲我不喜歡也不看好這項技術!那爲什麼又要寫呢?因爲目前公司的項目中在用,無論我喜不喜歡都需要使用,我的吃飯啊!

我是不會在自己可以主導的項目中主動使用此技術的,那爲什麼我這麼討厭它呢?

主要是因爲我認爲其會給項目維護帶來糟糕的體驗。DataBinding使的程序員可以在layout文件中寫代碼了,也就是可以將業務邏輯混合在視圖文件中了,這不僅降低了layout文件的重用性,還使View與業務邏輯一定程度綁定了。雖然Google一直在強調,不要再layout文件中使用複雜的表達式,但是你要知道給同一個項目提交代碼的不僅有經驗豐富的王二狗,也會有實習生牛翠花,還可能有外包林蛋大,code review 在很多公司根本沒有或者就是一個擺設。

但是你也不用太擔心,雖然我不喜歡它但是不妨礙喜歡它的你學習此項技術。我準備以3篇文章總結一下這個庫的一些知識

  1. 使用入門
  2. Binding Adatper,雙向綁定等
  3. 與LiveData 等架構組件配合,以及原理等

DataBinding 總覽

我們知道,Android的UI一般是使用 xml 格式的layout文件表示的, 要想爲UI上的view賦值,首先需要在代碼中獲取到相應的view,即 findViewById

最開始那一幫寫Android的也沒覺得有什麼不好,大家都這麼用,世界一片和諧。但是突然有些不安分的程序員(例如JakeWharton)不幹了:這太TM繁瑣了,能不能有更好的辦法呢, 於是參考其他程序員的想法寫出了 ButterKnife 。就這樣又過了兩年,隨着Android生態的壯大與穩定,Google Android 團隊終於有時間開始搞事情了,於是Jetpack橫空出世。DataBinding也被收歸其旗下了,是其中解決View綁定的庫,但是感覺一下用力過猛,弄成DataBinding了,最近又出了ViewBinding,也許是一個糾正吧。我認爲ViewBinding纔是解決這個問題的希望,強烈建議閱讀文章 秒懂Android開發之ViewBinding,一代神器ButterKnife的終結者

本文包含如下內容:

  1. DataBinding 簡單介紹
  2. DataBinding 試圖解決的問題及其使用場景
  3. DataBinding 的入門使用

簡介

Data Binding 類庫是 Android Jetpack 的一部分,通過它你可以將數據與UI元素的綁定工作(就是互相賦值)在layout 文件中以聲明的方式完成,而不是在viewControlor,例如Activity,Fragment 中。

例如我們要給一個Textview賦值,傳統方式代碼如下:

findViewById<TextView>(R.id.user_namet).apply {
    text = viewModel.userName
}

而使用data binding後就可以將賦值的邏輯放到layout文件中了。

<TextView
	...
    android:text="@{viewmodel.userName}" />

整體來說呢就這麼點東西,但是鋪開了還是有些看頭的,所以小夥伴們搬好小板凳,準備開講。

解決的問題及其使用場景

解決的問題主要有兩點:

  1. 省去程序員自己調用 findViewById獲取UI元素,使用程序生成
  2. 數據與UI相互賦值問題,包括事件

data binding的精髓應該在第二點上,如果你僅僅是想去掉煩人的findViewById ,那麼Google新推出的 ViewBinding 更加適合,因爲其簡單而高效。

實戰使用

紙上得來終覺淺,絕知此事要躬行。看半天如果自己不動手寫一下,那都是一團漿糊,等到用的時候還是不會,讓我們一起coding起來

前提:Android Studio 4.0

我們準備開發如下圖所示的一個頁面,通過下面兩個按鈕動態修改紅框中的文字
在這裏插入圖片描述

  1. 打開data binding 功能
    在要使用data binding 的Module 的gradle 文件中如下配置即可
android{
	...
	    buildFeatures {
       		 dataBinding = true
    }
}

如果使用Kotlin 請記得使用 kotlin-kapt 插件

apply plugin: 'kotlin-kapt'

注意:如果你的項目引用了一個使用了data binding的類庫,那麼你就被綁架了,你也必須開啓data binding,所以如果你在寫一個類庫,請慎重使用此技術。

  1. 將你的layout文件改成data binding 要求的格式
<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 >
		...
    </data>

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

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

最外層必須是<layout>標籤,那個<data>標籤裏面存放要在layout中引用的數據。那個ConstraintLayout 纔是我們需要的UI.

值得說明的是,AndroidStudio支持將普通的layout轉換爲dataBinding需要的layout格式。

在需要轉換的layout文件中外層View右鍵,選擇Context Actions,然後選擇轉換爲data binding layout 即可。如下圖所示
在這裏插入圖片描述

  1. 與ViewControlor綁定

    即讓我們的Activity等視圖控制器與data binding 生成的類綁定,如下所示

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityDataBindingBinding =
                     DataBindingUtil.setContentView(this, R.layout.activity_data_binding)
    }

這裏使用了DataBindingUtil 來進行綁定,除此之外,那個layout文件的生成類ActivityDataBindingBinding裏還有幾個靜態inflate(...)方法可以用於綁定.

  1. 在layout文件中書寫表達式

當完成以上3步後就可以在layout文件裏面寫表達式了。

首先在<data> 標籤裏面聲明聲明變量,聲明好了就可以在表達式中引用了,例如本例中聲明瞭viewModel作爲變量。

    <data >
        <variable
            name="viewModel"
            type="top.ss007.androiddevmemo.databinding.DataBindingViewModel" />
    </data>

第二在view中書寫表達式,在表達式中就可以引用我們聲明的變量了,例如我的ViewMode文件如下

class DataBindingViewModel : ViewModel() {

    var action: String = "邀請牛翠花晚上一起生猴子"
    var targetGirl: Girl = Girl("牛翠花",30)


    fun seduceGirl(girl: Girl) {
        targetGirl = Girl("上官無雪", 18)
        action = "邀請${girl.age.toString() + "的" + girl.name}晚上一起看月亮"
    }

    fun bornSon(girl: Girl) {
        targetGirl = Girl("牛翠花", 30)
        action = "邀請${girl.age.toString() + "的" + girl.name}晚上一起生猴子"
    }

}

其中Girl 是一個普通的data class

我就可以使用其中的變量和方法了

爲TextView 賦值

        <TextView
            android:id="@+id/tv_action"
            ...
            android:text="@{viewModel.action}"/>

爲Button設置點擊事件

        <Button
            android:id="@+id/btn_born_son"
			...
            android:onClick="@{(view)->viewModel.bornSon(viewModel.targetGirl)}"
            />

那到此是不是就已經好了呢?非常可惜,還差最後一步,因爲你想想,你在layout中聲明瞭viewModel變量,但是我們沒有爲其賦值啊,那他肯定是個null,所以視圖中自然也獲取不到值。

值得說明的是,其不會崩潰,因爲dataBinding做了處理,這點還是比較讚的。

  1. 給layout文件中聲明的變量賦值
        override fun onCreate(savedInstanceState: Bundle?) {
        ...
        val viewModel = ViewModelProvider(this).get(DataBindingViewModel::class.java)
        binding.viewModel = viewModel
    }
    

完成以上5步後就大功告成了,感覺自己好牛逼。但是當你滿心歡喜的去點擊下面的按鈕時,UI盡然沒有任何反應! 納尼?what happened? 什麼情況?穩住,我們能懂。。。

綁定可觀察數據(observable data)

我們在點擊按鈕時更新了數據,但是發現UI並沒有更新,這不是我們想要的啊。那是因爲我們的數據是普通的數據,要想當數據改變時通知UI,需要此數據爲observable data

可觀察數據分爲三類

  • Objects

實現了androidx.databinding.Observable 接口的類,google給很貼心的幫我們實現了一個BaseObservable, 我們一般都是繼承這個類, 負責在屬性值改變時通知data binding一下。

方法爲:用@Bindable 標記getter, 同時在setter裏調用notifyPropertyChanged方法 即可。

例如本例代碼如下

class Girl : BaseObservable() {
    @get:Bindable
    var name: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.name)
        }

    @get:Bindable
    var age: Int = 18
        set(value) {
            field = value
            notifyPropertyChanged(BR.age)
        }
}
  • Fields

dataBinding 類庫提供的封裝 ObservableField<T>,例如要使一個String變量可以觀察可如下定義:

val action: ObservableField<String> = ObservableField("邀請牛翠花晚上一起生猴子")

其還爲int, boolean, long 等基礎類型提供了相應的實現,相比ObservableField其在進行訪問操作時不進行裝箱和拆箱,效率有所提高。

ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable

  • Collections
    ObservableArrayMapObservableArrayList

運行結果

當把我們的數據修改爲可Observable data後再次運行,點擊按鈕時,UI也會隨之改變。

在這裏插入圖片描述

總結

至此,相信你已經可以非常自信的上手DataBinding了,你今天又不用加班了,開心哇??

在文中我沒有過多的提及layout中表達式的語法,一是因爲本文目的是讓你快速上手,二是因爲我認爲這個在你使用遇到困難時查官方文檔纔是正解。

下一篇讓我們一起看一下 Binding Adapter 以及雙向綁定。

如果你覺得對你有用,請反手給我一個贊,如果你還想隨時找到我,請猛戳關注按鈕。

望你保重身體,享受編碼,享受生活。

本文源碼下載地址:AndroidDevMemo
官方教程:Data Binding Library

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章