<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                還記得在博客[《高逼格UI-ASD(Android Support Design)》](http://blog.csdn.net/qibin0506/article/details/46850763)的開始曾經說過,Android最新推出了一個官方的數據綁定框架-Data Binding Library。現在github上也有很多三方的數據綁定框架,但是我們為什么要選擇官方的呢?恩,答對了。就是因為是官方的,三方的東西說不定什么時候作者一步高興就停止更新了,官方的就不一樣了,我們可以看到它漸漸的穩定起來。好了廢話不多說,從這篇博客開始,我們就來了解一下android最新給我們帶來的數據綁定框架——Data Binding Library。數據綁定框架給我們帶來了更大的方便性,以前我們可能需要在`Activity`里寫很多的`findViewById`,煩人的代碼也增加了我們代碼的耦合性,現在我們馬上就可以拋棄*那么多*的`findViewById`。說到這里,有人可能會有個疑問:我使用一些注解框架也可以不用`findViewById`啊,是的,但是注解注定要拖慢我們代碼的速度,Data Binding則不會,官網文檔說*還會提高解析XML的速度*,最主要的Data Binding并不是單單減少了我們的`findViewById`,更多好處請往下看文章。 一、環境 在開始使用新東西之前,我們需要稍微的配置一下環境,這里要求你的Android Studio版本是**1.3+**,使用eclipse的同學暫時還沒有辦法使用該框架,請換用Android Studio。還有,在開始之前,請更新你的`Support repository`到最新的版本。 萬事俱備,那我們就開始搭配環境! 新建一個`project`,在`dependencies`中添加以下依賴 ~~~ classpath "com.android.databinding:dataBinder:1.0-rc1" ~~~ 新建`module`,并且在`module`的build.gradle文件中添加 ~~~ apply plugin: 'com.android.application' apply plugin: 'com.android.databinding' ~~~ ok,到現在為止,我們的環境就準備完畢了,下面我們就開始Data Binding的學習啦。 二、Data Binding嘗試 在代碼開始,我們并不直接進入新東西的講解,而且以一段代碼展現Data Binding的魅力。 首先我們需要一個`java bean`,很簡單,一個學生類。 ~~~ public class Student { private String name; private String addr; public Student() { } public Student(String name, String addr) { this.name = name; this.addr = addr; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddr() { return this.addr; } public void setAddr(String addr) { this.addr = addr; } } ~~~ 再來看看我們布局文件怎么寫: ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="stu" type="org.loader.androiddatabinding.Student" /> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{stu.name}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{stu.addr}"/> </LinearLayout> </layout> ~~~ 可以看到我們的xml布局和以前還有有一定的差別的,但是差別也不是很大。 最后來看看`Activity`怎么寫。 ~~~ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.setStu(new Student("loader", "山東萊蕪")); } } ~~~ `Activity`的代碼非常簡單,就添加了兩行代碼,而且,值得注意的是:我們并沒有`findViewById`然后再去`setText`。 這段小代碼運行的結果大家可能已經猜到了,就是在界面上顯示`loader`和`山東萊蕪`兩句話。 ![](https://box.kancloud.cn/2016-02-18_56c55b3a526b6.jpg "") ) 在看完小實例后,大家是不是感覺棒棒噠? 沒有了之前的find控件,沒有了setText,`Activity`代碼更加簡潔明了! 下面開始,我們進入Data Binding的學習! 三、 初始Data Binding 上面的代碼算是帶領我們進入了Data Binding的世界,那我們先從布局文件開始入手Data Binding吧。再來看看上面的布局文件。 ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="stu" type="org.loader.androiddatabinding.Student" /> </data> ... </layout> ~~~ 我們的根節點變成了`layout`,在`layout`的子節點中分成兩部分,第一部分是`data`節點,第二部分才是我們之前的根節點,在`data`節點下我們又定義了一個`variable`, 從名稱上看,這應該是一個變量,變量的名稱是`stu`,類型是`org.loader.androiddatabinding.Student`,這類似我們在java文件中這么定義: ~~~ org.loader.androiddatabinding.Student stu; ~~~ ok,這樣很好理解了吧,不過這里要寫`Student`完整的包名,一個還好,如果這里我們需要多個`Student`呢?要累死? NO,NO,NO,我們還可以向寫java文件那樣導入包。 ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <import type="org.loader.app2.Student" /> <variable name="stu" type="Student" /> </data> ... </layout> ~~~ 這樣寫,就類似于java的 ~~~ import org.loader.app2.Student; ... Student stu; ... ~~~ 既然變量我們定義好了,那該怎么使用呢?還是看上面的xml文件。 ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> ... <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{stu.name}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{stu.addr}"/> </LinearLayout> </layout> ~~~ 恩,注意看兩個`TextView`的`android:text`,它的值是一個以`@`開始,以{}包裹的形式出現,而內容呢?是`stu.name`。stu就是我們上面定義的`variable`, name還記得嗎?是我們`Student`類中的一個變量。其實這里就會去調用`stu.getName()`方法。 好了,很快,我們就入門了Data Binding,下面讓我們來多定義幾個變量試試看。 ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <import type="org.loader.app2.Student" /> <variable name="stu" type="Student" /> <variable name="str" type="String"/> <variable name="error" type="boolean"/> <variable name="num" type="int" /> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{stu.name}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{str}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{String.valueOf(num)}"/> </LinearLayout> </layout> ~~~ 來看看定義的變量,多了好幾個,有一個`String`類型的變量我們并沒有導包,這里說明一下,和在java里一樣,`java.lang`包里的類,我們是可以不用導包的,再往下,一個`boolean`和`int`類型的變量,都是java基本類型的,所以說嘛,在這里定義變量,你就想成是在java里定義就ok。 再來看看這幾個`TextView`,第二個,我們直接使用`@{str}`來為`android:text`設置成上面定義個`str`的值,繼續往下要注意了,我們使用了 ~~~ android:text="@{String.valueOf(num)}" ~~~ 來設置了一個`int`類型的變量,大家都知道我們在給`android:text`設置`int`類型的值時一定要轉化為`String`類型,要不它就認為是資源文件了,這里我們還學到了一點,在xml中,我們不僅可以使用變量,而且還可以調用方法! 四、 變量定義的高級部分 在上面,我們學會了如何去在xml中定義變量,但是不知道你發現沒?我們沒有定義像`List`、`Map`等這樣的集合變量。那到底能不能定義呢?答案肯定是可以的,而且定義的方式和我們上面的基本一致,區別就在于我們還需要為它定義key的變量,例如: ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <import type="org.loader.app2.Student" /> <import type="android.graphics.Bitmap" /> <import type="java.util.ArrayList" /> <import type="java.util.HashMap" /> <variable name="stu" type="Student" /> <variable name="str" type="String"/> <variable name="error" type="boolean"/> <variable name="num" type="int" /> <variable name="list" type="ArrayList&lt;String>" /> <variable name="map" type="HashMap&lt;String, String>" /> <variable name="array" type="String[]" /> <variable name="listKey" type="int" /> <variable name="mapKey" type="String" /> <variable name="arrayKey" type="int" /> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{stu.name}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{str}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{String.valueOf(num)}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{list[listKey]}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{map[`name`]}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{array[0]}"/> </LinearLayout> </layout> ~~~ 這段代碼比較長,但是我們僅關心那幾個集合和數組,可以看到我們定義集合和定義普通變量一樣,只不過這里我們還指定了一些的泛型,例如:`ArrayList&lt;String>`。 下面我們還為下面使用這些集合準備了幾個key,也都是變量。 繼續看看怎么使用,和我們在java中使用不同,這里都是以:集合變量名[key]的形式使用,如果你的key是一個字面字符串可以使用反引號,也可以使用轉義后的雙引號。恩,這里也沒有什么可以說的了,大家多看幾遍就掌握了,都是概念性的東西,記住就ok。 五、在java代碼中使用 前面定義了這么多變量,但是我們還沒有給他們賦值!在哪賦值呢?肯定是在java代碼中使用了,大部分情況我們還是在`Activity`中去使用它,以前我們都是在`onCreate`方法中通過`setContentView`去設置布局,但現在不一樣了,現在我們是用過`DataBindingUtil`類的一個靜態方法`setContentView`設置布局,同時該方法會返回一個對象,什么對象?這個對象有點特殊,它是一個自動生成的類的對象,看下面: ~~~ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); } ~~~ 看到`ActivityMainBinding`了嗎?就是它!那自動生成有什么規則了沒?當然有了,記好了 > 將我們布局文件的首字母大寫,并且去掉下劃線,將下劃線后面的字母大寫,加上Binding組成。 看看上面的類,是不是符合這個規則。繼續看看這個對象哪來的,是通過 ~~~ DataBindingUtil.setContentView(this, R.layout.activity_main); ~~~ 返回的,DataBindingUtil.setContentView的兩個參數分別是當前`Activity`和布局文件。那接下來,就是我們關心的給變量賦值了。 ~~~ @Override protected void onCreate(Bundle savedInstanceState) { ... binding.setStu(new Student("loader")); binding.setStr("string"); binding.setError(false); ArrayList<String> list = new ArrayList<String>() { { add("arraylist"); } }; binding.setList(list); binding.setListKey(0); HashMap<String, String> map = new HashMap<String, String>() { { put("name", "hashmap"); } }; binding.setMap(map); // binding.setMapKey("name"); String[] array = new String[1]; array[0] = "array"; binding.setArray(array); binding.setArrayKey(0); } ~~~ 一連串的binding.setXXX,這個XXX是什么呢?就是我們在xml中定義的那些變量首字母大寫了!也沒好好說的吧,多看幾遍。 六、 表達式 短暫的幸福時光,我們還是要告別java代碼了,繼續回到xml中,這一塊,我們來學習一下表達式,什么?這玩意在xml中還支持表達式! ~~~ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text='@{error ? "error" : "ok"}'/> ~~~ 還記得上面我們定義了一個boolean的變量沒有用到,這里我們就用到了,看好`android:text`,這里是一個三元表達式,如果error是true,則text就是error,否則是ok。這里還支持null合并操作,什么是null合并,相信看一眼你就知道了 ~~~ android:text='@{str==null ?? "not null"}' ~~~ 簡單解釋一下,如果str是null,text的值就是str本身,否則就是”not null”。 它還支持一下表達式: - Mathematical + - / * % - String concatenation + - Logical && || - Binary & | ^ - Unary + - ! ~ - Shift >> >>> << - Comparison == > < >= <= - instanceof - Grouping () - Literals - character, String, numeric, null - Cast - Method calls - Field access - Array access [] - Ternary operator ?: 但是它不支持一下表達式: - this - super - new - Explicit generic invocation 七、 其他遺漏點 說到這里,xml中的事情基本算完了,但是還有幾個小地方沒有說,順便說一下。 1. 設置別名 假如我們import了兩個相同名稱的類咋辦?別怕,別名來拯救你!例如: ~~~ ... <data> <import type="xxx.Name" alias="MyName"> <import type="xxx.xx.Name"> </data> <TextView xxx:@{MyName.getName()}> <TextView xxx:@{Name.getName()}> ... ~~~ 1. 自定義Binding名稱 還記得系統為我們生成好的那個binding類名嗎?如果只能使用那樣的是不是有點太暴力了?好在google對我們還算友好了,允許我們自定義binding名稱,定制名稱也很簡單,就是給data一個class字段就ok。 例如: ~~~ <data class=".Custom"> ... </data> ~~~ 那么:DataBindingUtils.setContentView返回的binding類就是:`你的應用包名.Custom`。 八、事件綁定 大家都知道,在xml中我們可以給`button`設置一個`onClick`來達到事件的綁定,現在DataBinding也提供了事件綁定,而且不僅僅是`button`。 來看一下: ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <import type="org.loader.app3.EventHandlers" /> <variable name="handlers" type="EventHandlers" /> </data> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CLICK ME" android:onClick="@{handlers.handleClick}"/> </LinearLayout> </layout> ~~~ 定義了一個`EventHandlers`類型的`handlers`變量,并在onClick的時候執行`EventHandlers`的`handleClick`方法。 繼續看看EventHandlers是怎么寫的。 ~~~ public class EventHandlers { public void handleClick(View view) { Toast.makeText(view.getContext(), "you clicked the view", Toast.LENGTH_LONG).show(); } } ~~~ 很簡單,就是簡單的`Toast`了一下,這里要注意的是,`handlerClick`方法需要一個`View`的參數。 九、 數據對象 我們學會了通過binding為我們的變量設置數據,但是不知道你有沒有發現一個問題,當我們數據改變的時候會怎樣?數據是跟隨著改變呢?還是原來的數據呢?這里告訴你答案:很不幸,顯示的還是原來的數據?那有沒有辦法讓數據源發生變化后顯示的數據也隨之發生變化?先來想想`ListView`是怎么做的, `ListView`的數據是通過`Adapter`提供的,當數據發生改變時,我們通過`notifyDatasetChanged`通過UI去改變數據,這里面的原理其實就是內容觀察者,慶幸的是DataBinding也支持內容觀察者,而且使用起來也相當方便! BaseObservable 我們可以通過Observable的方式去通知UI數據已經改變了,當然了,官方為我們提供了更加簡便的方式`BaseObservable`,我們的實體類只需要繼承該類,稍做幾個操作,就能輕松實現數據變化的通知。如何使用呢? 首先我們的實體類要繼承`BaseObservale`類,第二步在`Getter`上使用注解`@Bindable`,第三步,在`Setter`里調用方法`notifyPropertyChanged`,第四步,完成。就是這么簡單,下面我們來實際操作一下。 首先定義一個實體類,并繼承`BaseObservable` ~~~ public class Student extends BaseObservable { private String name; public Student() { } public Student(String name) { this.name = name; } @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(org.loader.app4.BR.name); } } ~~~ 觀察getName方法,我們使用了`@Bindable`注解,觀察setName,我們調用了`notifyPropertyChanged`方法,這個方法還需要一個參數,這里參數類似于`R.java`,保存了我們所有變量的引用地址,這里我們使用了name。 再來看看布局文件。 ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data class=".Custom"> <import type="org.loader.app4.Student" /> <variable name="stu" type="Student"/> <variable name="click" type="org.loader.app4.MainActivity" /> </data> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{click.click}" android:text="@{stu.name}"/> </layout> ~~~ 不多說了,我們給`TextView`設置了文本,還有點擊事件。Activity, ~~~ public class MainActivity extends AppCompatActivity { private Student mStu; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); org.loader.app4.Custom binding = DataBindingUtil.setContentView(this, R.layout.activity_main); mStu = new Student("loader"); binding.setStu(mStu); binding.setClick(this); } public void click(View view) { mStu.setName("qibin"); } } ~~~ 這段代碼,首先顯示的是loader,當我們點擊`TextView`時,界面換成qibin。 ObservableFields家族 上面使用`BaseObservable`已經非常容易了,但是google工程師還不滿足,繼續給我們封裝了一系列的`ObservableFields`,這里有`ObservableField`,`ObservableBoolean`,`ObservableByte`,`ObservableChar`,`ObservableShort`,`ObservableInt`,`ObservableLong`,`ObservableFloat`,`ObservableDouble`,`ObservableParcelable` ObservableFields的使用方法就更加簡單了,例如下面代碼, ~~~ public class People { public ObservableField<String> name = new ObservableField<>(); public ObservableInt age = new ObservableInt(); public ObservableBoolean isMan = new ObservableBoolean(); } ~~~ 很簡單,只有三個ObservableField變量,并且沒有getter和setter,因為我們不需要getter和setter。 在xml中怎么使用呢? ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data class=".Custom"> <variable name="people" type="org.loader.app4.People" /> </data> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{people.name}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{String.valueOf(people.age)}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text='@{people.isMan ? "man" : "women"}'/> </LinearLayout> </layout> ~~~ 也很簡單,直接使用變量,那怎么賦值和取值呢?這些ObservableField都會有一對`get`和`set`方法,所以使用起來也很方便了: ~~~ ... mPeople = new People(); binding.setPeople(mPeople); mPeople.name.set("people"); mPeople.age.set(19); mPeople.isMan.set(true); ... ~~~ 也不多說了。 Observable Collections 既然普通的變量我們有了ObservableFields的分裝,那集合呢?當然也有啦,來看著兩個:`ObservableArrayMap`,`ObservableArrayList`。使用和普通的Map、List基本相同,直接看代碼: ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data class=".Custom"> <variable name="map" type="android.databinding.ObservableArrayMap&lt;String,String>" /> <variable name="list" type="android.databinding.ObservableArrayList&lt;String>" /> </data> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{map[`name`]}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{list[0]}"/> </LinearLayout> </layout> ~~~ 在布局中,使用方式和普通的集合一樣,如果看不太懂,可以往上翻博客,看上面的集合是怎么使用的。 在來看java文件,怎么設置數據, ~~~ ObservableArrayMap<String, String> map = new ObservableArrayMap<>(); ObservableArrayList<String> list = new ObservableArrayList<>(); map.put("name", "loader or qibin"); list.add("loader!!!"); binding.setMap(map); binding.setList(list); ~~~ 哦,太簡單了,簡直和`List`、`Map`使用方法一模一樣!!! 好了,不多說了,大家也都看累了吧。 那就先說到這里,其他的下篇博客我們繼續學習。 [demo源碼下載,戳這里](http://download.csdn.net/detail/qibin0506/8983229)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看