瞭解DataBinding的使用,請參考:
如果你暫時無法翻牆,看這篇文章也可以。
本文中,默認的View就是Activity及其對應的XML文件。
第一部分:DataBinding入門
配置項
在Android中,需要使用DataBinding來支持MVVM的雙向綁定。
在Android中的DataBinding需要在module下的build.gradle中申明:
android {
// ......
dataBinding{
enabled = true
}
// ......
}
Layout標籤使用
想讓DataBinding
生效,還需要在View
對應的XML中間中使用layout
標籤,它就像個命名空間一樣。類似於:
<?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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
在這個layout
標籤包裹的命名空間下,有一個data
標籤,你可以通過該標籤,在View
的XML文件中引入Model
的變量,這個留在後面說。
我們前面說了在MVVM中,Activity
和對應的XML文件共同組成了View
,那麼它們是怎麼聯繫到一起得呢?
一般來說,XML文件,通過Activity的setContentView函數,將XML文件,交給Activity控制。就像這樣:
setContentView(R.layout.activity_main);
那麼,在DataBinding框架下,我們得換個新得姿勢:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
}
setContentView
的函數名相同,但調用實例卻從傳統的Activity換成了DataBindingUtil
的靜態函數。
聰明的小夥伴已經注意到了,爲啥莫名其妙多了個ActivityMainBinding類?這不是我乾的!!!!解釋一下。
當你在XML文件中正確的添加了<layout></layout>
標籤時,AndroidStudio會通過DataBinding框架,自動生成了一個類,這個類的包名遵循如下規則:
規則一:項目包名.databinding.XML文件去掉下劃線首字母大寫+Binding
例如,我的XML文件名稱爲activity_main.xml,通過DataBinding框架生成的包類名爲:
com.dali.mvvmdemo.databinding.ActivityMainBinding;
其實,從這種簡單的命名規則中也可以看出,通過DataBindingUtil.setContentView
將哪個xml文件綁定到activity,函數的返回值就是遵循了規則一的類實例。
那麼binding類的命名就只能使用DataBinding框架生成的麼?當然不是,DataBinding的<data>
標籤中,可以定義當前xml生成binding類的類名。像這樣:
<data class="CustomBinding">
<variable
name="person"
type="com.superli.mvvmdemo.User" />
</data>
class
的值就是自定義binding類的類名,它的固定類全名爲:com.superli.mvvmdemo.databinding.CustomBinding;
這意味着,在所有使用到該類的地方,你需要添加的導入語句是:
import com.superli.mvvmdemo.databinding.CustomBinding;
比如在Activity中。
通過這個實例,我們可以直接操作xml文件中所有帶id
的view
,而再也不用findViewById
了。
上述就是最簡單的DataBinding的使用了,經過了這兩步,你運行起來的APP,就可以說使用了DataBinding框架。我們來小結一下,基本步驟:
- 在Activity對應的XML文件中,在最外層包裹
<layout></layout>
標籤,使DataBinding框架生成對應的binding類。 - 在activity中,通過
DataBindingUtil.setContentView
,將Xml以Binding實例的方式,提供給activity操作。
數據綁定
我們已經知道,在通過DataBindingUtil.setContentView
函數,獲取了xml對應的binding實例之後,可以通過該實例操作xml文件。那麼具體怎麼做呢?
還是先從xml文件說起,前面提到,DataBinding的<layout></layout>
類似於一個命名空間,在該空間下,包含了一個<data></data>
標籤和<variable/>
標籤。看一下示例:
<?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="person"
type="com.dali.mvvmdemo.User" />
</data>
<!-- 其它佈局代碼 -->
</layout>
這裏有兩個陌生的標籤:<data>
和 <variable>
<data>
標籤:表示標籤內的代碼都將作爲xml的binding類的一部分。<variable>
標籤:該標籤中,申明瞭一個變量,和它對應的類。type表示類,name表示變量名,編譯時,DataBinding將會把改變量申明到xml對應的binding類中。
那麼,這段代碼有啥用呢?
xml文件有了這段申明後,就可以在xml文件中自由的使用com.dali.mvvmdemo.User
類型的所有成員變量或者函數了,當然,還是得通過類的實例變量person
。
第一種綁定方法
一種比較典型的用法如下:
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{String.valueOf(person.mAge), default="Default"}'
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_name"/>
使用“@{}”將需要使用的變量包裹起來,中間就可以像寫Java代碼一樣使用了。因爲這裏的person.mAge
是int類型,所以使用String.valueOf
將數值類型轉換成了字符串類型。
default="Default"
:表示,在佈局文件預覽時顯示的值。
通常xml生成的binding類中,直接引用了java.lang包下的類,所以我們這裏可以直接使用String類型,當基本類型無法滿足你時,你可以通過
<import type="com.dali.mvvmdemo.User"/>
導入你需要的類型,當然,這部分暫時不開展。
User此時就是個簡單的JavaBean類:
public class User {
public String mName;
public int mAge;
public User(String name, int age){
mName = name;
mAge = age;
}
}
綁定是綁定了,那麼數據從哪兒來呢?看完下一個代碼片段,你就明白了:
public class MainActivity extends AppCompatActivity {
private User user = new User("SuperLi", 3);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setPerson(user); // 將xml中的person變量和當前對象中的user變量綁定起來。
}
}
當xml的variable標籤中,申明瞭變量名稱後,DataBinding會在生成的xml binding類中,生成對應的setXXX
函數,以便將類實例的引用賦值給binding類中對應的變量XXX
。
例如:我的activity_main.xml的binding類是:ActivityMainBindingImpl,在activity_main.xml中有person變量申明如下:
<variable
name="person"
type="com.dali.mvvmdemo.User" />
那麼,ActivityMainBindingImpl類中,將會生成如下代碼:
public class ActivityMainBindingImpl extends ActivityMainBinding {
// ...
public void setPerson(@Nullable com.dali.mvvmdemo.User Person) {
this.mPerson = Person;
// ...
}
// ...
}
這是最常用最經典的綁定方式。
第二種常規方式
另外一種就是View
的Id
直接設置數據。還是以之前的xml代碼爲例:
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(person.mAge)}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_name"/>
TextView
的id爲tv_age
,xml的binding類生成時,會有一個tvAge
的成員變量,通過它,可以操作當前TextView
,比如:
binding.tvAge.setText("1000");
和binding類名生成的規則類似,以下劃線分割,第二個名字開始首字母大寫。只不過TextView的id作爲變量名稱首字母小寫,binding類作爲類名首字母大寫而已。