注:主要參考精通 Android Data Binding,官方文檔,感謝分享。
第一步:創建xml布局
創建一個布局xml文件,就像以前一樣,我們需要在那個view中使用,就按照固定寫法操作。在這個框架下我們的思維要稍稍改變一下了,以前的布局XML只描述了布局,它是相對固定的東西,在Data Binding Library下我們的布局XML就像是一個類,他可以有變量也能進行一定的運算。其實Data Binding Library還真的給你生成了一個類似這樣的類(這個類在綁定數據時會用到,命名規則:activity_main.xml—》ActivityMainBinding)。
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"><!--layout層,不是常見的5種布局;命名空間--> <data> <import type="com.xfyb.mvvmtest.User"></import><!--導包,一次導入,下面都可以使用該類。前提是我們已經創建出來了該類--> <variable name="user" type="User"/><!--創建對象--> </data> <!--原有的文件--> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}"/><!--View中使用變量用@{} 格式來調用--> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="change" android:text="change"/> </LinearLayout></layout>第二步:定義數據對象 在上面中我們提到需要創建User的對象,因此我們需要將其創建出來。
public class User { PRivate String Name; public void setAge(int age) { this.age = age; } public void setName(String name) { Name = name; } private int age; public User(String name, int age) { Name = name; this.age = age; } public int getAge() { return age; } public String getName() { return Name; }}這個類就是一個簡單的Bean類,也就是我們在View中需要調用的對象屬性。
第三步:綁定數據
public class MainActivity extends AppCompatActivity { User user; ActivityMainBinding binding;//自動生成的類ActivityMainBinding其實就是代表了那個布局,里面包括了布局的View,我們聲明的變量。 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* setContentView(R.layout.activity_main);*/ binding = DataBindingUtil.setContentView(this, R.layout .activity_main);//原來設置布局的setContentView改成了DataBindingUtil.setContentView user = new User("XK",18);//創建對象,賦初始值 binding.setUser(user); } public void change (View view){ user.setName("KX"); binding.setUser(user); }}基于以上三步,我們就將基于Data Binding 的MVVM的簡單編寫就完成了,當我們實際運行時,如下界面:
但是當我們點擊BUTTON時發現無法更改name的值,無法刷新textView。 解決方案: 1、讓實體類繼承BaSEObservable類
修改后的代碼如下所示:
public class User extends BaseObservable {//繼承自BaseObservable private String Name; public void setAge(int age) { this.age = age; } public void setName(String name) { Name = name; } private int age; public User(String name, int age) { Name = name; this.age = age; } @Bindable//添加注解 public int getAge() { return age; } @Bindable public String getName() { return Name; }}當我們再次點擊時,就會修改name屬性的值。
至此我們對于MVVM的簡單應用就完成了,對于此應用我們主要是注意書寫的規范及格式就可以了,特別是對于xml的文件的配置、User類的注解和綁定數據使用時的規范。
總結: 使用基于Data Binding的操作有以下優勢:
1、不需要在Activity里寫很多的findViewById2、在xml中我們只需要通過import導入需要的類的全包名,下面都可以使用。3、引用綁定數據的對象時的格式:以@開始,以{}包裹的形式出現,而內容呢?是user.name。user就是我們上面定義的variable。1、使用類中方法
定義一個靜態方法public static String capitalize(final String Word) { if (word.length() > 1) { return String.valueOf(word.charAt(0)).toUpperCase() + word.substring(1); } return word; }在 xml 的 data 節點中導入: <import type="com.xfyb.mvvmtest.MyStringUtils"></import>使用方法與 java 語法一樣:<TextView android:text="@{MyStringUtils.capitalize(user.name)}" android:layout_width="wrap_content" android:layout_height="wrap_content"/>總結:
使用類中的方法,注意方法的參數和返回值,否則無法正常生成ActivityMainBinding類,導致編譯失敗使用類中的方法,與常見的java一樣,可以是通過靜態方法,也可以與簡單應用中對于name的引用一樣采用“variable”的格式。
2、類型別名 如果我們在 data 節點了導入了兩個同名的類怎么辦?
<import type="com.example.home.data.User" /><import type="com.examle.detail.data.User" /><variable name="user" type="User" />這樣一來出現了兩個 User 類,那 user 變量要用哪一個呢?不用擔心,import 還有一個 alias 屬性。
<import type="com.example.home.data.User" /><import type="com.examle.detail.data.User" alias="DetailUser" /><variable name="user" type="DetailUser" />3、Null Coalescing 運算符
android:text="@{user.displayName ?? user.lastName}"就等價于
android:text="@{user.displayName != null ? user.displayName : user.lastName}"4、屬性值 通過 @{} 可以直接把 Java 中定義的屬性值賦值給 xml 屬性。
<TextView android:text="@{user.lastName}" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>5、Observable Binding 要實現 Observable Binding,首先得有一個 implement 了接口 android.databinding.Observable 的類,為了方便,Android 原生提供了已經封裝好的一個類 - BaseObservable,并且實現了監聽器的注冊機制。我們可以直接繼承 BaseObservable。
public class User extends BaseObservable { private String Name; public void setAge(int age) { this.age = age; notifyPropertyChanged(BR.age); } public void setName(String name) { Name = name; notifyPropertyChanged(BR.name);//通知改變屬性 } private int age; public User(String name, int age) { Name = name; this.age = age; } @Bindable public int getAge() { return age; } @Bindable public String getName() { return Name; }}BR 是編譯階段生成的一個類,功能與 R.java 類似,用 @Bindable 標記過 getter 方法會在 BR 中生成一個 entry。 通過代碼可以看出,當數據發生變化時還是需要手動發出通知。 通過調用 notifyPropertyChanged(BR.firstName) 可以通知系統 BR.firstName 這個 entry 的數據已經發生變化,需要更新 UI。
6、帶 ID 的 View 在使用Data Binding 有效降低了代碼的冗余性,甚至完全沒有必要再去獲取一個 View 實例。我們可以直接在xml中使用id就可以了
<TextView android:id="@+id/tv_show" android:layout_width="wrap_content" android:layout_height="wrap_content"/>在代碼中我們可以直接通過banding中找到(類似于java中的類和屬性)。
binding.tvShow.setText("xxxx");//直接同對象.屬性 獲取到運行后的效果:
新聞熱點
疑難解答