日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android?DataBinding類關系深入探究_Android

作者:昉鈺 ? 更新時間: 2022-12-12 編程語言

一、在相應的板塊中開啟DataBinding

? ? dataBinding {
? ? ? ? enabled true
? ? }

二、DataBing的簡單使用

這里寫一個簡單的布局,如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginVertical="12dp"
        android:text="Alice"
        android:textColor="#333333"
        android:textSize="18sp"
        app:layout_constraintBottom_toTopOf="@id/second"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />
    <TextView
        android:id="@+id/second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Bob"
        android:textColor="#999"
        android:textSize="14sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/first" />
</androidx.constraintlayout.widget.ConstraintLayout>

沒錯,就是一個包含兩個TextView的布局,雖然簡單,但是也能說明DataBinding的原理;但是按照DataBinding對布局的要求,這并不符合它的要求,所以需要改成如下:

<?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.zfang.databindingstudy.module.SimpleViewModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <TextView
            android:id="@+id/first"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginVertical="12dp"
            android:text="@{viewModel.first}"
            android:textColor="#333333"
            android:textSize="18sp"
            app:layout_constraintBottom_toTopOf="@id/second"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed" />
        <TextView
            android:id="@+id/second"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.second}"
            android:textColor="#999"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/first" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

仔細觀察下變動,兩個方面:

1、最外層多了一個layout

2、TextView的賦值使用表達式@{viewModel.xxx}來完成。

然后在Activity中如下使用生成的類:

class MainActivity : AppCompatActivity() {
    private val viewModel: SimpleViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.lifecycleOwner = this
        binding.viewModel = viewModel
    }
}

相應的ViewModel類如下:

class SimpleViewModel: ViewModel() {
    private val _first = MutableLiveData("Alice")
    private val _second = MutableLiveData("Bob")
    val first: LiveData<String> = _first
    val second: LiveData<String> = _second
}

運行應用出來的結果正在預料之中,這里就不貼圖國;可能你會好奇,DataBinding是如何把數據和布局自動綁定的呢?下面就來解密下是怎么回事。

三、生成的xml布局

在Activity中使用的布局名稱是activity_main,生存的輔助類的名字為ActivityMainBinding,這里的ActivityMainBinding是我們直接能夠使用到的類,其實除了這個輔助類,還生存了另外兩個輔助xml文件,只是我們在代碼中使用不到而已。

生存的第一個布局文件內容如下(路徑:DataBindingStudy\app\build\intermediates\incremental\debug\mergeDebugResources\stripped.dir\layout\activity_main.xml):

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:tag="layout/activity_main_0"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginVertical="12dp"
        android:tag="binding_1"
        android:textColor="#333333"
        android:textSize="18sp"
        app:layout_constraintBottom_toTopOf="@id/second"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />
    <TextView
        android:id="@+id/second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:tag="binding_2"
        android:textColor="#999"
        android:textSize="14sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/first" />
</androidx.constraintlayout.widget.ConstraintLayout>

看到沒,這正是Android原生的布局的文件(在我們之前寫的布局的基礎上去掉了layout標簽),只是做了點變動;多了一個tag屬性,這里看不出這個屬性是干什么用的,但后面我們會知道他的作用。

生存的第二個xml文件如下(路徑:DataBindingStudy\app\build\intermediates\data_binding_layout_info_type_merge\debug\out\activity_main-layout.xml):

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Layout directory="layout" filePath="app\src\main\res\layout\activity_main.xml"
    isBindingData="true" isMerge="false" layout="activity_main"
    modulePackage="com.zfang.databindingstudy" rootNodeType="androidx.constraintlayout.widget.ConstraintLayout">
    <Variables name="viewModel" declared="true"
        type="com.zfang.databindingstudy.module.SimpleViewModel">
        <location endLine="8" endOffset="70" startLine="6" startOffset="8" />
    </Variables>
    <Targets>
        <Target tag="layout/activity_main_0"
            view="androidx.constraintlayout.widget.ConstraintLayout">
            <Expressions />
            <location endLine="41" endOffset="55" startLine="11" startOffset="4" />
        </Target>
        <Target id="@+id/first" tag="binding_1" view="TextView">
            <Expressions>
                <Expression attribute="android:text" text="viewModel.first">
                    <Location endLine="21" endOffset="44" startLine="21" startOffset="12" />
                    <TwoWay>false</TwoWay>
                    <ValueLocation endLine="21" endOffset="42" startLine="21" startOffset="28" />
                </Expression>
            </Expressions>
            <location endLine="28" endOffset="63" startLine="16" startOffset="8" />
        </Target>
        <Target id="@+id/second" tag="binding_2" view="TextView">
            <Expressions>
                <Expression attribute="android:text" text="viewModel.second">
                    <Location endLine="34" endOffset="45" startLine="34" startOffset="12" />
                    <TwoWay>false</TwoWay>
                    <ValueLocation endLine="34" endOffset="43" startLine="34" startOffset="28" />
                </Expression>
            </Expressions>
            <location endLine="40" endOffset="61" startLine="30" startOffset="8" />
        </Target>
    </Targets>
</Layout>

這個文件就是基于前面的布局文件解析生存而來,里面的元素分別對應到我們布局文件里面的兩個TextView,這里拿最后一個元素說下,如下:

<Target id="@+id/second" tag="binding_2" view="TextView">
    <Expressions>
        <Expression attribute="android:text" text="viewModel.second">
            <Location endLine="34" endOffset="45" startLine="34" startOffset="12" />
            <TwoWay>false</TwoWay>
            <ValueLocation endLine="34" endOffset="43" startLine="34" startOffset="28" />
        </Expression>
    </Expressions>
    <location endLine="40" endOffset="61" startLine="30" startOffset="8" />
</Target>

Target里面的id就是布局里面的id,tag就是布局里面的tag,view代表了View的類型。在Expression里面的text屬性就代表了需要執行的表達式,里面還有個屬性TwoWay,代表是不是雙向綁定,當然這里不是雙向綁定,所以為false。

四、生存的代碼

除了生存前面說的兩個xml文件,DataBinding還生存了相關的輔助類方便我們在Activity中使用,如下圖所示:

xx

?????DataBinding生成的類

ActivityMainBinding、ActivityMainBindingImpl:這兩個類的名字是根據布局文件的名字產生的,我們使用的布局文件名字為:activity_main,它這里就是把下劃線去掉,然后按照駝峰式命名法再加上后綴Binding或者BindingImpl生成而來的。相關的類繼承關系如下:

這里的BaseObservable是觀察者模式的基類,ViewBinding就是一個接口(畫圖工具沒找到虛線的前頭),ViewDataBinding是Databinding的核心類,也是們的重點分析對象,而這里的ActivityMainBinding、ActivityMainBindingImpl就是根據我布局文件生成的兩個輔助類,主要是用于輔助數據綁定相關的工作。

這里的有兩個文件名一樣的類DataBinderMapperImpl,但其實他們的功能是不一樣的。左邊的DataBinderMapperImpl類(位于包androidx.databinding下面,可以認為是android提供給的,只不過是由apt在項目編譯期間生存而來)會調用右邊的DataBinderMapperImpl(位于我們自己的包下面)為他工作,你可以認為全部的工作都是在右邊的DataBinderMapperImpl完成的,左邊那個主要起了一個中間轉發的作用。

到這里關于DataBinding生存的類關系說明就完成了,下一章DataBinding原理----布局的加載將說明DataBinding是如何加載布局的。

原文鏈接:https://blog.csdn.net/www586089/article/details/127760345

欄目分類
最近更新