昨天咱們一塊兒學習了dataBinding的基礎用法,我想你可能還停留在它只是不用再findViewById,其實否則,今天咱們就來擴展延伸,看看這個框架到底有什麼魔力讓谷歌官方大力推崇。這裏還沒看昨天的基礎運用的須要去看一看,附上連接:http://www.cnblogs.com/liushilin/p/5681473.htmlhtml
項目已經同步至github:https://github.com/nanchen2251/databindingjava
昨天咱們解決了簡單的使用以及在xml中進行屬性的變換和一些簡單的表達式放在xml文件中的使用問題,你們確定有所疑問,咱們在實際開發中確定會用到不少的佈局重用等,那麼在這個框架中能否一樣作到呢?另外,若是咱們想用這個框架實現圖片加載呢?你們都知道圖片在xml中只能經過src設置本地圖片,並無提供經過url設置的屬性,別急,樓主會把這個方法分享給你。android
1)首先把昨天的xml代碼放到一個獨立的xml文件中,樓主這裏叫user_layout.xml,這裏設置圖片經過使用app自定義屬性設置圖片urlgit
1 <?xml version="1.0" encoding="utf-8"?> 2 <layout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 xmlns:app="http://schemas.android.com/apk/res-auto"> 6 <data> 7 <variable 8 name="user" 9 type="com.example.nanchen.databindingdemo.User"> 10 </variable> 11 </data> 12 13 <LinearLayout 14 android:layout_width="0dp" 15 android:layout_weight = "1" 16 android:layout_height="match_parent" 17 android:gravity="center" 18 android:orientation="vertical" 19 tools:context="com.example.nanchen.databindingdemo.MainActivity"> 20 21 <ImageView 22 android:layout_width="100dp" 23 android:layout_height="100dp" 24 app:imageUrl="@{ user.icon }"/> 25 26 <TextView 27 android:layout_width="wrap_content" 28 android:layout_height="wrap_content" 29 android:textSize="25sp" 30 android:onClick="@{user.clickName}" 31 android:textColor="@{user.vip? 0xffff0000:0xff000000}" 32 android:text="@{user.nickName + `(` + user.name +`)`}"/> 33 34 <TextView 35 android:layout_width="wrap_content" 36 android:layout_height="wrap_content" 37 android:textSize="25sp" 38 android:onLongClick="@{user.longClickNickName}" 39 android:text="@{user.nickName ?? user.name}"/> 40 41 <TextView 42 android:layout_width="wrap_content" 43 android:layout_height="wrap_content" 44 android:textSize="25sp" 45 android:textColor="@{user.level < 3 ? 0xff03bbf9 : 0xfff60bdb }" 46 android:text="@{user.email}"/> 47 </LinearLayout> 48 </layout>
2)而後修改主頁面的xml文件,activity_main.xml,因爲咱們使用的是左右對稱顯示兩個用戶,因此咱們應該用list,而不是以前的user,其中用到的尖括號用轉義方法上一節已經講過。github
<?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="user"--> <!--type="com.example.nanchen.databindingdemo.User">--> <!--</variable>--> <import type="com.example.nanchen.databindingdemo.User"/> <variable name="users" type="java.util.List<User>"/> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal" tools:context="com.example.nanchen.databindingdemo.MainActivity"> <include layout="@layout/user_layout" app:user="@{ users[0] }"/> <include layout="@layout/user_layout" app:user="@{ users[1] }"/> </LinearLayout> </layout>
3)再改下Activity的代碼網絡
package com.example.nanchen.databindingdemo; import android.databinding.DataBindingUtil; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import com.example.nanchen.databindingdemo.databinding.ActivityMainBinding; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.activity_main); ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main); User user = new User(); user.setName("劉世麟"); user.setNickName("南塵"); user.setEmail("liushilin@qq.com"); user.setVip(true); user.setLevel(5); user.setIcon("http://qlogo1.store.qq.com/qzone/503233512/503233512/100?1311741184"); // binding.setUser(user); User user1 = new User(); user1.setName("春春兒"); user1.setNickName(null); user1.setVip(false); user1.setEmail("nanchen@qq.com"); user1.setLevel(1); // binding.setUser(user1); List<User> list = new ArrayList<>(); list.add(user); list.add(user1); binding.setUsers(list); // binding.setUser(new User("劉世麟","南塵","liushilin@qq.com")); } }
看看運行效果app
看到這裏,也許小夥伴會說,切,不就一個include嗎,這個框架仍是沒帶來飛通常的感受,別急,還有更厲害的使用ListView之類的等着你框架
咱們來看看listView如何實現。ide
1)天然須要先定義一個list_item.xml,用於基本Item的佈局。佈局
1 <?xml version="1.0" encoding="utf-8"?> 2 3 <layout 4 xmlns:android="http://schemas.android.com/apk/res/android" 5 xmlns:app="http://schemas.android.com/apk/res-auto"> 6 7 <data> 8 <variable 9 name="user" 10 type="com.example.nanchen.databindingdemo.User"/> 11 </data> 12 13 <LinearLayout 14 android:layout_width="match_parent" 15 android:layout_height="match_parent" 16 android:orientation="horizontal" 17 android:onClick="@{ user.click }"> 18 19 <ImageView 20 android:layout_width="100dp" 21 android:layout_height="100dp" 22 app:imageUrl="@{user.icon}"/> 23 24 <TextView 25 android:layout_width="match_parent" 26 android:layout_height="match_parent" 27 android:text="@{user.name}" 28 android:gravity="center"/> 29 30 </LinearLayout> 31 </layout>
2)寫一個通用的適配器Adaper,注意這裏和你以往寫的ListView的適配器徹底不同,咱們多了兩個屬性,一個是layoutId,一個是屬性id
1 package com.example.nanchen.databindingdemo; 2 3 import android.content.Context; 4 import android.databinding.DataBindingUtil; 5 import android.databinding.ViewDataBinding; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.BaseAdapter; 10 11 import java.util.List; 12 13 /** 14 * ListView的通用Adapter 15 * Created by 南塵 on 16-7-18. 16 */ 17 public class CommonAdapter<T> extends BaseAdapter { 18 private Context context;//上下文環境 19 private List<T> list;//通用的,不知道數據 20 private int layoutId;//通用的,不知道佈局 21 private int variableId;//變量的id 22 23 /** 24 * 構造方法 25 */ 26 public CommonAdapter(Context context, List<T> list, int layoutId, int variableId) { 27 this.context = context; 28 this.list = list; 29 this.layoutId = layoutId; 30 this.variableId = variableId; 31 } 32 33 @Override 34 public int getCount() { 35 if (list!=null) 36 return list.size(); 37 return 0; 38 } 39 40 @Override 41 public Object getItem(int position) { 42 return list.get(position); 43 } 44 45 @Override 46 public long getItemId(int position) { 47 return position; 48 } 49 50 @Override 51 public View getView(int position, View convertView, ViewGroup parent) { 52 ViewDataBinding binding = null; 53 if (convertView == null){ 54 binding = DataBindingUtil.inflate(LayoutInflater.from(context),layoutId,parent,false); 55 }else{ 56 binding = DataBindingUtil.getBinding(convertView); 57 } 58 binding.setVariable(variableId,list.get(position)); 59 return binding.getRoot(); 60 } 61 }
3)在xml中佈局,這個比較簡單,先在配置文件中把這個更改成程序入口,而且添加網絡操做權限,這裏用了BR文件,BR文件和R文件都是系統會自動生成的,只是R文件用於資源的id。圖片咱們就使用一個默認的
1 package com.example.nanchen.databindingdemo; 2 3 import android.databinding.DataBindingUtil; 4 import android.os.Bundle; 5 import android.support.v7.app.AppCompatActivity; 6 7 import com.example.nanchen.databindingdemo.databinding.ActivityDataBindingListBinding; 8 9 import java.util.ArrayList; 10 import java.util.List; 11 12 public class DataBindingListActivity extends AppCompatActivity { 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 // setContentView(R.layout.activity_data_binding_list); 18 ActivityDataBindingListBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_data_binding_list); 19 20 List<User> list = new ArrayList<>(); 21 for (int i = 0; i < 100; i++) { 22 User user = new User(); 23 user.setName("用戶 " + i ); 24 user.setIcon("http://qlogo1.store.qq.com/qzone/503233512/503233512/100?1311741184"); 25 list.add(user); 26 } 27 CommonAdapter<User> adapter = new CommonAdapter<>( 28 this, list, R.layout.list_item, com.example.nanchen.databindingdemo.BR.user); 29 binding.setAdapter(adapter); 30 31 } 32 33 34 }
4)大概能夠運行了哈。
5)如何添加點擊事件呢?別慌,在咱們的User中加入點擊方法就行了。
1 package com.example.nanchen.databindingdemo; 2 3 import android.view.View; 4 import android.widget.Toast; 5 6 /** 7 * 繼承,觀察可刷新 8 * Created by 南塵 on 16-7-18. 9 */ 10 public class User { 11 private String name;//用戶名 12 private String nickName;//暱稱 13 private String email;//郵箱 14 15 private boolean vip;//是不是會員 16 private int level;//級別 17 private String icon; 18 19 public String getIcon() { 20 return icon; 21 } 22 23 public void setIcon(String icon) { 24 this.icon = icon; 25 } 26 27 public int getLevel() { 28 return level; 29 } 30 31 public void setLevel(int level) { 32 this.level = level; 33 } 34 35 public boolean isVip() { 36 return vip; 37 } 38 39 public void setVip(boolean vip) { 40 this.vip = vip; 41 } 42 43 public User() { 44 } 45 46 public User(String name, String nickName, String email) { 47 this.name = name; 48 this.nickName = nickName; 49 this.email = email; 50 } 51 52 public String getEmail() { 53 return email; 54 } 55 56 public void setEmail(String email) { 57 this.email = email; 58 } 59 60 public String getName() { 61 return name; 62 63 } 64 65 public void setName(String name) { 66 this.name = name; 67 } 68 69 public String getNickName() { 70 return nickName; 71 } 72 73 public void setNickName(String nickName) { 74 this.nickName = nickName; 75 } 76 77 public void clickName(View view){ 78 Toast.makeText(view.getContext(),"點擊了用戶名:" + name,Toast.LENGTH_SHORT).show(); 79 } 80 81 public boolean longClickNickName(View view){ 82 Toast.makeText(view.getContext(),"長按了暱稱:"+nickName,Toast.LENGTH_SHORT).show(); 83 return true; 84 } 85 86 public void click(View view){ 87 setName(getName() + "( 已點擊 )"); 88 } 89 }
6)這裏咱們點擊了用戶2,什麼狀況?沒刷新!!!!!,哦,哪裏出了問題!
7)調皮的滑動了一下滾動條,再回去發現才刷新更改了。
9)e duo key,這裏也太out了吧,說好的最屌框架呢?說好的要愉快一生呢?
仔細一看,才發現咱們的邏輯中出了一點小問題,這樣的話雖然你的list中的數據改變了,可是list並不知道,而這個adapter又沒有刷新數據的方法,怎麼辦?
這裏用到一個觀察者模式,只須要把User繼承BaseObservable類,而且在要更改的屬性上加一個@Bindble,再在setName方法中加入這樣一句話則可。
//刷新變量(變量id)
notifyPropertyChanged(com.example.nanchen.databindingdemo.BR.name);
1 package com.example.nanchen.databindingdemo; 2 3 import android.databinding.BaseObservable; 4 import android.databinding.Bindable; 5 import android.view.View; 6 import android.widget.Toast; 7 8 /** 9 * 繼承,觀察可刷新 10 * Created by 南塵 on 16-7-18. 11 */ 12 public class User extends BaseObservable { 13 private String name;//用戶名 14 private String nickName;//暱稱 15 private String email;//郵箱 16 17 private boolean vip;//是不是會員 18 private int level;//級別 19 private String icon; 20 21 public String getIcon() { 22 return icon; 23 } 24 25 public void setIcon(String icon) { 26 this.icon = icon; 27 } 28 29 public int getLevel() { 30 return level; 31 } 32 33 public void setLevel(int level) { 34 this.level = level; 35 } 36 37 public boolean isVip() { 38 return vip; 39 } 40 41 public void setVip(boolean vip) { 42 this.vip = vip; 43 } 44 45 public User() { 46 } 47 48 public User(String name, String nickName, String email) { 49 this.name = name; 50 this.nickName = nickName; 51 this.email = email; 52 } 53 54 public String getEmail() { 55 return email; 56 } 57 58 public void setEmail(String email) { 59 this.email = email; 60 } 61 62 @Bindable 63 public String getName() { 64 return name; 65 66 } 67 68 public void setName(String name) { 69 this.name = name; 70 //刷新變量(變量id) 71 notifyPropertyChanged(com.example.nanchen.databindingdemo.BR.name); 72 } 73 74 public String getNickName() { 75 return nickName; 76 } 77 78 public void setNickName(String nickName) { 79 this.nickName = nickName; 80 } 81 82 public void clickName(View view){ 83 Toast.makeText(view.getContext(),"點擊了用戶名:" + name,Toast.LENGTH_SHORT).show(); 84 } 85 86 public boolean longClickNickName(View view){ 87 Toast.makeText(view.getContext(),"長按了暱稱:"+nickName,Toast.LENGTH_SHORT).show(); 88 return true; 89 } 90 91 public void click(View view){ 92 setName(getName() + "( 已點擊 )"); 93 } 94 }
10)再次運行:
如今好多了嘛,一點擊就刷新了,是否是很吊?額,如今是點擊整個item均可以刷新屬性界面,好吧,其實不管你點擊哪裏,只要你加上這個click方法做爲自定義屬性,均可以實現這個功能,這裏你要在原來的思路上實現是否是至關麻煩,而這個框架讓你只須要移動一行代碼的位置就能夠,很高端大氣上檔次有木有?
這裏作個示範,假如你是點擊頭像更改,只須要這樣。
1 <?xml version="1.0" encoding="utf-8"?> 2 3 <layout 4 xmlns:android="http://schemas.android.com/apk/res/android" 5 xmlns:app="http://schemas.android.com/apk/res-auto"> 6 7 <data> 8 <variable 9 name="user" 10 type="com.example.nanchen.databindingdemo.User"/> 11 </data> 12 13 <LinearLayout 14 android:layout_width="match_parent" 15 android:layout_height="match_parent" 16 android:orientation="horizontal" 17 > 18 19 <ImageView 20 android:layout_width="100dp" 21 android:layout_height="100dp" 22 app:imageUrl="@{user.icon}" 23 android:onClick="@{ user.click }"/> 24 25 <TextView 26 android:layout_width="match_parent" 27 android:layout_height="match_parent" 28 android:text="@{user.name}" 29 android:gravity="center"/> 30 31 </LinearLayout> 32 </layout>
不只能夠放在這裏,你還能夠放在任何地方,不管是在ListView裏面仍是外面。
確定這個框架還有其餘的東西的,你們一塊兒發掘咯~