玩轉Android之MVVM開發模式實戰,炫酷的DataBinding!

原文:http://blog.csdn.net/u012702547/article/details/52077515

---------------------------------------------------------

MVP可以結合android的DataBinding

-------------------------以下轉載---------------

C# 很早就有了MVVM的開發模式,Android手機中的MVVM一直到去年Google的I\O大會上才推出,姍姍來遲。MVVM這中開發模式的優點自不必多說,可以實現視圖和邏輯代碼的解耦,而且,按照Google的說法,使用了MVVM的開發模式,還可以提高布局文件的解析速度,個人覺得這一點非常重要。我們在安卓開發中經常需要寫很多個findViewById,讓人心煩,很多人不想寫這個于是用了一些注解框架,可是注解框架無論性能多好,效率總是要低于findViewById的,因此,Android中的MVVM也即databinding可以幫助我們徹底解決這個問題。OK,廢話不多說,我們來看看具體要怎么在Android開發中使用MVVM。

在低版本的AndroidStudio中使用DataBinding稍微有點麻煩,這里不做介紹。我這里以AndroidStuido2.1為例來介紹DataBinding。本文主要包含以下幾方面內容:


1.基本使用

2.綁定ImageView

3.綁定ListView

4.點擊事件處理

5.數據更新處理

好了,那就開始吧!

1.基本使用

創建好一個Android Project之后,在gradle文件中添加如下幾行代碼,表示開啟databinding:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. android?{??
  2. ????...??
  3. ????...??
  4. ????...??
  5. ????dataBinding{??
  6. ????????enabled?true??
  7. ????}??
  8. }??

就是這么簡單,一個簡單的databinding配置之后,就可以開始使用數據綁定了。

要使用數據綁定,我們得首先創建一個實體類,比如User實體類,如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. /**?
  2. ?*?Created?by?王松?on?2016/7/31.?
  3. ?*/??
  4. public?class?UserEntity?{??
  5. ????private?String?username;??
  6. ????private?String?nickname;??
  7. ????private?int?age;??
  8. ??
  9. ????public?UserEntity()?{??
  10. ????}??
  11. ??
  12. ????public?int?getAge()?{??
  13. ????????return?age;??
  14. ????}??
  15. ??
  16. ????public?void?setAge(int?age)?{??
  17. ????????this.age?=?age;??
  18. ????}??
  19. ??
  20. ????public?String?getNickname()?{??
  21. ????????return?nickname;??
  22. ????}??
  23. ??
  24. ????public?void?setNickname(String?nickname)?{??
  25. ????????this.nickname?=?nickname;??
  26. ????}??
  27. ??
  28. ????public?String?getUsername()?{??
  29. ????????return?username;??
  30. ????}??
  31. ??
  32. ????public?void?setUsername(String?username)?{??
  33. ????????this.username?=?username;??
  34. ????}??
  35. ??
  36. ????public?UserEntity(int?age,?String?nickname,?String?username)?{??
  37. ????????this.age?=?age;??
  38. ????????this.nickname?=?nickname;??
  39. ????????this.username?=?username;??
  40. ????}??
  41. }??

然后我們來看看布局文件該怎么寫,首先布局文件不再是以傳統的某一個容器作為根節點,而是使用<layout></layout>作為根節點,在<layout>節點中我們可以通過<data>節點來引入我們要使用的數據源,如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <layout??
  3. ????xmlns:android="http://schemas.android.com/apk/res/android"??
  4. ????>??
  5. ??
  6. ????<data>??
  7. ??
  8. ????????<variable??
  9. ????????????name="user"??
  10. ????????????type="org.lenve.databinding1.UserEntity"/>??
  11. ????</data>??
  12. ??
  13. ????<LinearLayout??
  14. ????????xmlns:tools="http://schemas.android.com/tools"??
  15. ????????android:layout_width="match_parent"??
  16. ????????android:layout_height="match_parent"??
  17. ????????android:orientation="vertical"??
  18. ????????tools:context="org.lenve.databinding1.MainActivity">??
  19. ??
  20. ????????<TextView??
  21. ????????????android:layout_width="wrap_content"??
  22. ????????????android:layout_height="wrap_content"??
  23. ????????????android:text="@{user.username}"/>??
  24. ??
  25. ????????<TextView??
  26. ????????????android:layout_width="wrap_content"??
  27. ????????????android:layout_height="wrap_content"??
  28. ????????????android:text="@{user.nickname}"/>??
  29. ??
  30. ????????<TextView??
  31. ????????????android:layout_width="wrap_content"??
  32. ????????????android:layout_height="wrap_content"??
  33. ????????????android:text="@{String.valueOf(user.age)}"/>??
  34. ????</LinearLayout>??
  35. </layout>??

在data中定義的variable節點,name屬性表示變量的名稱,type表示這個變量的類型,實例就是我們實體類的位置,當然,這里你也可以換一種寫法,如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <data>??
  2. ??
  3. ????<import?type="org.lenve.databinding1.UserEntity"/>??
  4. ????<variable??
  5. ????????name="user"??
  6. ????????type="UserEntity"/>??
  7. </data>??

先使用import節點將UserEntity導入,然后直接使用即可。但是如果這樣的話又會有另外一個問題,假如我有兩個類都是UserEntity,這兩個UserEntity分屬于不同的包中,又該如何?看下面:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <data>??
  2. ??
  3. ????<import?type="org.lenve.databinding1.UserEntity"?alias="Lenve"/>??
  4. ????<variable??
  5. ????????name="user"??
  6. ????????type="Lenve"/>??
  7. </data>??


在import節點中還有一個屬性叫做alias,這個屬性表示我可以給該類取一個別名,我給UserEntity這個實體類取一個別名叫做Lenve,這樣我就可以在variable節點中直接寫Lenve了。

看完data節點我們再來看看布局文件,TextView的text屬性被我直接設置為了@{user.username},這樣,該TextView一會直接將UserEntity實體類的username屬性的值顯示出來,對于顯示age的TextView,我用了String.valueOf來顯示,因為大家知道TextView并不能直接顯示int型數據,所以需要一個簡單的轉換,事實上,我們還可以在{}里邊進行一些簡單的運算,這些我一會再說。

最后,我們來看看Activity中該怎么寫,setContentView方法不能夠再像以前那樣來寫了,換成下面的方式:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. DataBindingUtil.setContentView(this,?R.layout.activity_main)??

該方法有一個返回值,這個返回值就是系統根據我們的activity_main.xml布局生成的一個ViewModel類,所以完整寫法如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. ActivityMainBinding?activityMainBinding?=?DataBindingUtil.setContentView(this,?R.layout.activity_main);??

有了ViewModel,再把數據綁定上去就可以了,如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. @Override??
  2. protected?void?onCreate(Bundle?savedInstanceState)?{??
  3. ????super.onCreate(savedInstanceState);??
  4. ????ActivityMainBinding?activityMainBinding?=?DataBindingUtil.setContentView(this,?R.layout.activity_main);??
  5. ????UserEntity?user?=?new?UserEntity();??
  6. ????user.setAge(34);??
  7. ????user.setUsername("zhangsan");??
  8. ????user.setNickname("張三");??
  9. ????activityMainBinding.setUser(user);??
  10. }??


運行,顯示效果如下:

OK,那我們剛才還說到可以在@{}進行簡單的計算,都有哪些計算呢?我們來看看:

1.基本的三目運算

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <TextView??
  2. ????android:layout_width="wrap_content"??
  3. ????android:layout_height="wrap_content"??
  4. ????android:text="@{user.username??user.nickname}"/>??

兩個??表示如果username屬性為null則顯示nickname屬性,否則顯示username屬性。

2.字符拼接

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <TextView??
  2. ????android:layout_width="wrap_content"??
  3. ????android:layout_height="wrap_content"??
  4. ????android:text="@{`username?is?:`+user.username}"/>??

大家注意,這里的字符拼接不是用單引號哦,用的是ESC按鍵下面那個按鍵按出來的。目前DataBinding中的字符拼接還不支持中文。

3.根據數據來決定顯示樣式

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <TextView??
  2. ????android:layout_width="wrap_content"??
  3. ????android:layout_height="wrap_content"??
  4. ????android:background="@{user.age?&lt;?30???0xFF0000FF:0xFFFF0000}"??
  5. ????android:text="@{String.valueOf(user.age)}"/>??
我在這里給TextView設置背景的時候,做了一個簡單的判斷,如果用戶的年齡小于30,背景就顯示為藍色,否則背景就顯示為紅色,DataBinding里支持小于號但是不支持大于號,索性,大于小于號我都用轉義字符來表示。


另外,DataBinding對于基本的四則運算、邏輯與、邏輯或、取反位移等都是支持的,我這里不再舉例。


2.綁定ImageView

OK,上文只是一個簡單的綁定文本,下面我們來看看怎么樣綁定圖片,這里我們還得介紹DataBinding的另一項新功能,就是關于DataBinding自定義屬性的問題,事實上,在我們使用DataBinding的時候,可以給一個控件自定義一個屬性,比如我們下面即將說的這個綁定ImageView的案例。假設我現在想要通過Picasso顯示一張網絡圖片,正常情況下這個顯示很簡單,可是如果我要通過DataBinding來實現,該怎么做呢?我們可以使用

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. @BindingAdapter??

注解來創建一個自定義屬性,同時還要有一個配套的注解的方法。當我們在布局文件中使用這個自定義屬性的時候,會觸發這個被我們注解的方法,這樣說大家可能還有一點模糊,我們來看看新的實體類:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. /**?
  2. ?*?Created?by?王松?on?2016/7/31.?
  3. ?*/??
  4. public?class?User?{??
  5. ????private?String?username;??
  6. ????private?String?userface;??
  7. ??
  8. ????public?User()?{??
  9. ????}??
  10. ??
  11. ????public?User(String?userface,?String?username)?{??
  12. ????????this.userface?=?userface;??
  13. ????????this.username?=?username;??
  14. ????}??
  15. ??
  16. ????@BindingAdapter("bind:userface")??
  17. ????public?static?void?getInternetImage(ImageView?iv,?String?userface)?{??
  18. ????????Picasso.with(iv.getContext()).load(userface).into(iv);??
  19. ????}??
  20. ??
  21. ????public?String?getUserface()?{??
  22. ????????return?userface;??
  23. ????}??
  24. ??
  25. ????public?void?setUserface(String?userface)?{??
  26. ????????this.userface?=?userface;??
  27. ????}??
  28. ??
  29. ????public?String?getUsername()?{??
  30. ????????return?username;??
  31. ????}??
  32. ??
  33. ????public?void?setUsername(String?username)?{??
  34. ????????this.username?=?username;??
  35. ????}??
  36. }??

新類里邊只有兩個屬性,分別是用戶名和用戶圖像,用戶圖像中存儲的實際上是一個網絡圖片地址,這里除了基本的get/set方法之外還多了一個叫做getInternetImage的網絡方法,這個方法有一個注解@BindAdapter("bind:userface"),該注解表示當用戶在ImageView中使用自定義屬性userface的時候,會觸發這個方法,我在這個方法中來為這個ImageView加載一張圖片,這里有一點需要注意,就是該方法必須為靜態方法。OK,我們再來看看這次的布局文件:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <layout??
  3. ????xmlns:android="http://schemas.android.com/apk/res/android"??
  4. ????xmlns:app="http://schemas.android.com/apk/res-auto"??
  5. ????>??
  6. ??
  7. ????<data>??
  8. ??
  9. ????????<variable??
  10. ????????????name="user"??
  11. ????????????type="org.lenve.databinding2.User"/>??
  12. ????</data>??
  13. ??
  14. ????<LinearLayout??
  15. ????????xmlns:tools="http://schemas.android.com/tools"??
  16. ????????android:layout_width="match_parent"??
  17. ????????android:layout_height="match_parent"??
  18. ????????android:orientation="vertical"??
  19. ????????tools:context="org.lenve.databinding2.MainActivity">??
  20. ??
  21. ????????<ImageView??
  22. ????????????android:id="@+id/iv"??
  23. ????????????android:layout_width="wrap_content"??
  24. ????????????android:layout_height="wrap_content"??
  25. ????????????app:userface="@{user.userface}"></ImageView>??
  26. ??
  27. ????????<TextView??
  28. ????????????android:layout_width="wrap_content"??
  29. ????????????android:layout_height="wrap_content"??
  30. ????????????android:text="@{user.username}"/>??
  31. ????</LinearLayout>??
  32. </layout>??

大家注意我在ImageView控件中使用userface屬性的時候,使用的前綴不是android而是app哦。再來看看Activity中的代碼:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. @Override??
  2. protected?void?onCreate(Bundle?savedInstanceState)?{??
  3. ????super.onCreate(savedInstanceState);??
  4. ????ActivityMainBinding?dataBinding?=?DataBindingUtil.setContentView(this,?R.layout.activity_main);??
  5. ????dataBinding.setUser(new?User("http://img2.cache.netease.com/auto/2016/7/28/201607282215432cd8a.jpg",?"張三"));??
  6. }??

就是這么簡單,加上網絡權限就可以運行了,運行效果如下:



3.綁定ListView

好了,看完了簡單使用之后,不知道你有沒有喜歡上DataBinding,如果還沒有,那就再來看看使用DataBinding來給ListView綁定數據吧,這個你一定會喜歡上的。因為使用這中方式來綁定太簡單了。

先來看看我們要做的效果吧:

就是一個ListView,左邊顯示圖片,右邊顯示文本,這樣一個效果。OK,那就一步一步來吧,先是主布局:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <RelativeLayout??
  3. ????xmlns:android="http://schemas.android.com/apk/res/android"??
  4. ????xmlns:tools="http://schemas.android.com/tools"??
  5. ????android:layout_width="match_parent"??
  6. ????android:layout_height="match_parent"??
  7. ????tools:context="org.lenve.databinding3.MainActivity">??
  8. ??
  9. ????<ListView??
  10. ????????android:id="@+id/lv"??
  11. ????????android:layout_width="match_parent"??
  12. ????????android:layout_height="match_parent"></ListView>??
  13. </RelativeLayout>??

主布局很簡單,就是一個ListView,再來看看ListView的item布局:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <layout??
  3. ????xmlns:android="http://schemas.android.com/apk/res/android"??
  4. ????xmlns:app="http://schemas.android.com/apk/res-auto"??
  5. ????>??
  6. ??
  7. ????<data>??
  8. ??
  9. ????????<variable??
  10. ????????????name="food"??
  11. ????????????type="org.lenve.databinding3.Food"/>??
  12. ????</data>??
  13. ??
  14. ????<RelativeLayout??
  15. ????????android:layout_width="match_parent"??
  16. ????????android:layout_height="96dp"??
  17. ????????android:orientation="vertical">??
  18. ??
  19. ????????<ImageView??
  20. ????????????android:id="@+id/iv"??
  21. ????????????android:layout_width="96dp"??
  22. ????????????android:layout_height="96dp"??
  23. ????????????android:padding="6dp"??
  24. ????????????app:img="@{food.img}"/>??
  25. ??
  26. ????????<TextView??
  27. ????????????android:id="@+id/description"??
  28. ????????????android:layout_width="match_parent"??
  29. ????????????android:layout_height="wrap_content"??
  30. ????????????android:layout_marginLeft="8dp"??
  31. ????????????android:layout_toRightOf="@id/iv"??
  32. ????????????android:ellipsize="end"??
  33. ????????????android:maxLines="3"??
  34. ????????????android:text="@{food.description}"/>??
  35. ??
  36. ????????<TextView??
  37. ????????????android:layout_width="wrap_content"??
  38. ????????????android:layout_height="wrap_content"??
  39. ????????????android:layout_marginLeft="8dp"??
  40. ????????????android:layout_toRightOf="@id/iv"??
  41. ????????????android:layout_alignParentBottom="true"??
  42. ????????????android:layout_marginBottom="2dp"??
  43. ????????????android:text="@{food.keywords}"??
  44. ????????????android:textStyle="bold"/>??
  45. ????</RelativeLayout>??
  46. </layout>??

圖片加載、文本加載前兩節都已經說過了,這里的東西就沒有什么難度了,我們再來看看實體類Food:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. /**?
  2. ?*?Created?by?王松?on?2016/7/31.?
  3. ?*/??
  4. public?class?Food?{??
  5. ????private?String?description;??
  6. ????private?String?img;??
  7. ????private?String?keywords;??
  8. ????private?String?summary;??
  9. ??
  10. ????public?Food()?{??
  11. ????}??
  12. ??
  13. ????public?Food(String?description,?String?img,?String?keywords,?String?summary)?{??
  14. ????????this.description?=?description;??
  15. ????????this.img?=?img;??
  16. ????????this.keywords?=?keywords;??
  17. ????????this.summary?=?summary;??
  18. ????}??
  19. ??
  20. ????@BindingAdapter("bind:img")??
  21. ????public?static?void?loadInternetImage(ImageView?iv,?String?img)?{??
  22. ????????Picasso.with(iv.getContext()).load(img).into(iv);??
  23. ????}??
  24. ??
  25. ????public?String?getDescription()?{??
  26. ????????return?description;??
  27. ????}??
  28. ??
  29. ????public?void?setDescription(String?description)?{??
  30. ????????this.description?=?description;??
  31. ????}??
  32. ??
  33. ????public?String?getImg()?{??
  34. ????????return?img;??
  35. ????}??
  36. ??
  37. ????public?void?setImg(String?img)?{??
  38. ????????this.img?=?img;??
  39. ????}??
  40. ??
  41. ????public?String?getKeywords()?{??
  42. ????????return?keywords;??
  43. ????}??
  44. ??
  45. ????public?void?setKeywords(String?keywords)?{??
  46. ????????this.keywords?=?keywords;??
  47. ????}??
  48. ??
  49. ????public?String?getSummary()?{??
  50. ????????return?summary;??
  51. ????}??
  52. ??
  53. ????public?void?setSummary(String?summary)?{??
  54. ????????this.summary?=?summary;??
  55. ????}??
  56. }??

這個實體類中有一個加載圖片的方法,加載方式我們上文都已經介紹過了,不多說。好了,再來看看我們的終極Adapter類:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. /**?
  2. ?*?Created?by?王松?on?2016/7/31.?
  3. ?*/??
  4. public?class?MyBaseAdapter<T>?extends?BaseAdapter?{??
  5. ????private?Context?context;??
  6. ????private?LayoutInflater?inflater;??
  7. ????private?int?layoutId;??
  8. ????private?int?variableId;??
  9. ????private?List<T>?list;??
  10. ??
  11. ????public?MyBaseAdapter(Context?context,?int?layoutId,?List<T>?list,?int?resId)?{??
  12. ????????this.context?=?context;??
  13. ????????this.layoutId?=?layoutId;??
  14. ????????this.list?=?list;??
  15. ????????this.variableId?=?resId;??
  16. ????????inflater?=?LayoutInflater.from(context);??
  17. ????}??
  18. ??
  19. ????@Override??
  20. ??
  21. ????public?int?getCount()?{??
  22. ????????return?list.size();??
  23. ????}??
  24. ??
  25. ????@Override??
  26. ????public?Object?getItem(int?position)?{??
  27. ????????return?list.get(position);??
  28. ????}??
  29. ??
  30. ????@Override??
  31. ????public?long?getItemId(int?position)?{??
  32. ????????return?position;??
  33. ????}??
  34. ??
  35. ????@Override??
  36. ????public?View?getView(int?position,?View?convertView,?ViewGroup?parent)?{??
  37. ????????ViewDataBinding?dataBinding;??
  38. ????????if?(convertView?==?null)?{??
  39. ????????????dataBinding?=?DataBindingUtil.inflate(inflater,?layoutId,?parent,?false);??
  40. ????????}else{??
  41. ????????????dataBinding?=?DataBindingUtil.getBinding(convertView);??
  42. ????????}??
  43. ????????dataBinding.setVariable(variableId,?list.get(position));??
  44. ????????return?dataBinding.getRoot();??
  45. ????}??
  46. }??

這個大概算是Adapter的終極寫法了,如果你按這種方式來寫Adapter,那么如果沒有非常奇葩的需求,你這個App中可能就只有這一個給ListView使用的Adapter了,為什么這么說呢?因為這個Adapter中沒有一個變量和我們的ListView沾邊,解釋一下幾個變量吧:layoutId這個表示item布局的資源id,variableId是系統自動生成的,根據我們的實體類,直接從外部傳入即可。另外注意布局加載方式為DataBindingUtil類中的inflate方法。OK,最后再來看看Activity:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. public?class?MainActivity?extends?AppCompatActivity?{??
  2. ??
  3. ????private?Handler?mHandler?=?new?Handler(){??
  4. ????????@Override??
  5. ????????public?void?handleMessage(Message?msg)?{??
  6. ????????????MyBaseAdapter<Food>?adapter?=?new?MyBaseAdapter<>(MainActivity.this,?R.layout.listview_item,?foods,?org.lenve.databinding3.BR.food);??
  7. ????????????lv.setAdapter(adapter);??
  8. ????????}??
  9. ????};??
  10. ????private?List<Food>?foods;??
  11. ????private?ListView?lv;??
  12. ??
  13. ????@Override??
  14. ????protected?void?onCreate(Bundle?savedInstanceState)?{??
  15. ????????super.onCreate(savedInstanceState);??
  16. ????????setContentView(R.layout.activity_main);??
  17. ????????lv?=?((ListView)?findViewById(R.id.lv));??
  18. ????????initData();??
  19. ????}??
  20. ??
  21. ????private?void?initData()?{??
  22. ????????OkHttpClient?client?=?new?OkHttpClient.Builder().build();??
  23. ????????Request?request?=?new?Request.Builder().url("http://www.tngou.net/api/food/list?id=1").build();??
  24. ????????client.newCall(request).enqueue(new?Callback()?{??
  25. ????????????@Override??
  26. ????????????public?void?onFailure(Call?call,?IOException?e)?{??
  27. ??
  28. ????????????}??
  29. ??
  30. ????????????@Override??
  31. ????????????public?void?onResponse(Call?call,?Response?response)?throws?IOException?{??
  32. ????????????????if?(response.isSuccessful())?{??
  33. ????????????????????parseJson(response.body().string());??
  34. ????????????????}??
  35. ????????????}??
  36. ????????});??
  37. ????}??
  38. ??
  39. ????private?void?parseJson(String?jsonStr)?{??
  40. ????????foods?=?new?ArrayList<>();??
  41. ????????try?{??
  42. ????????????JSONObject?jo?=?new?JSONObject(jsonStr);??
  43. ????????????JSONArray?tngou?=?jo.getJSONArray("tngou");??
  44. ????????????for?(int?i?=?0;?i?<?tngou.length();?i++)?{??
  45. ????????????????JSONObject?item?=?tngou.getJSONObject(i);??
  46. ????????????????String?description?=?item.getString("description");??
  47. ????????????????String?img?=?"http://tnfs.tngou.net/image"+item.getString("img");??
  48. ????????????????String?keywords?=?"【關鍵詞】?"+item.getString("keywords");??
  49. ????????????????String?summary?=?item.getString("summary");??
  50. ????????????????foods.add(new?Food(description,?img,?keywords,?summary));??
  51. ????????????}??
  52. ????????????mHandler.sendEmptyMessage(0);??
  53. ????????}?catch?(JSONException?e)?{??
  54. ????????????e.printStackTrace();??
  55. ????????}??
  56. ????}??
  57. }??

OkHttp下載數據和Json解析自不用多說,在構造MyAdapter的時候傳入的最后一個參數,是BR中的,這個BR和我們項目中的R文件類似,都是系統自動生成的。

至此,我們使用DataBinding的方式來給ListView加載數據就算完成了。so easy~~~

4.點擊事件處理

如果你使用DataBinding,我們的點擊事件也會有新的處理方式,首先以ListView為例來說說如何綁定點擊事件,在listview_item布局文件中每一個item的根節點添加如下代碼:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <layout??
  3. ????xmlns:android="http://schemas.android.com/apk/res/android"??
  4. ????xmlns:app="http://schemas.android.com/apk/res-auto"??
  5. ????>??
  6. ????....??
  7. ????....??
  8. ????<RelativeLayout??
  9. ????????android:layout_width="match_parent"??
  10. ????????android:layout_height="96dp"??
  11. ????????android:onClick="@{food.onItemClick}"??
  12. ????????android:orientation="vertical">??
  13. ??
  14. ????????<ImageView??
  15. ????????????android:id="@+id/iv"??
  16. ????????????android:layout_width="96dp"??
  17. ????????????android:layout_height="96dp"??
  18. ????????????android:padding="6dp"??
  19. ????????????app:img="@{food.img}"/>??
  20. ????????....??
  21. ????????....??
  22. ????????....??
  23. ????</RelativeLayout>??
  24. </layout>??

OK,我給RelativeLayout容器添了onClick屬性,屬性的值為food.onItemClick,那么這個onItemClick到底是什么呢?其實就是在實體類Food中定義的一個方法,如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. public?void?onItemClick(View?view)?{??
  2. ????Toast.makeText(view.getContext(),?getDescription(),?Toast.LENGTH_SHORT).show();??
  3. }??

點擊item獲取當前position的數據,獲取方式也是非常簡單,直接get方法獲取即可,比傳統的ListView的點擊事件通過position來獲取數據方便多了。如果我想為關鍵字這個TextView添加點擊事件也很簡單,和上面一樣,這里我就不再貼代碼了,文末可以下載源碼。

5. 數據更新處理

單純的更新Food對象并不能改變ListView的UI顯示效果,那該怎么做呢?Google給我們提供了三種解決方案,分別如下:

1.讓實體類繼承自BaseObservable

讓實體類繼承自BaseObservable,然后給需要改變的字段的get方法添加上@Bindable注解,然后給需要改變的字段的set方法加上notifyPropertyChanged(org.lenve.databinding3.BR.description);一句即可,比如我想點擊item的時候把description字段的數據全部改為111,我可以修改Food類變為下面的樣子:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. public?class?Food?extends?BaseObservable?{??
  2. ????private?String?description;??
  3. ????private?String?img;??
  4. ????private?String?keywords;??
  5. ????private?String?summary;??
  6. ??
  7. ????public?Food()?{??
  8. ????}??
  9. ??
  10. ????public?Food(String?description,?String?img,?String?keywords,?String?summary)?{??
  11. ????????this.description?=?description;??
  12. ????????this.img?=?img;??
  13. ????????this.keywords?=?keywords;??
  14. ????????this.summary?=?summary;??
  15. ????}??
  16. ??
  17. ????@BindingAdapter("bind:img")??
  18. ????public?static?void?loadInternetImage(ImageView?iv,?String?img)?{??
  19. ????????Picasso.with(iv.getContext()).load(img).into(iv);??
  20. ????}??
  21. ??
  22. ????public?void?onItemClick(View?view)?{??
  23. //????????Toast.makeText(view.getContext(),?getDescription(),?Toast.LENGTH_SHORT).show();??
  24. ????????setDescription("111");??
  25. ????}??
  26. ??
  27. ????public?void?clickKeywords(View?view)?{??
  28. ????????Toast.makeText(view.getContext(),?getKeywords(),?Toast.LENGTH_SHORT).show();??
  29. ????}??
  30. ??
  31. ??
  32. ????@Bindable??
  33. ????public?String?getDescription()?{??
  34. ????????return?description;??
  35. ????}??
  36. ??
  37. ????public?void?setDescription(String?description)?{??
  38. ????????this.description?=?description;??
  39. ????????notifyPropertyChanged(org.lenve.databinding3.BR.description);??
  40. ????}??
  41. ??
  42. ????public?String?getImg()?{??
  43. ????????return?img;??
  44. ????}??
  45. ??
  46. ????public?void?setImg(String?img)?{??
  47. ????????this.img?=?img;??
  48. ????}??
  49. ??
  50. ????public?String?getKeywords()?{??
  51. ????????return?keywords;??
  52. ????}??
  53. ??
  54. ????public?void?setKeywords(String?keywords)?{??
  55. ????????this.keywords?=?keywords;??
  56. ????}??
  57. ??
  58. ????public?String?getSummary()?{??
  59. ????????return?summary;??
  60. ????}??
  61. ??
  62. ????public?void?setSummary(String?summary)?{??
  63. ????????this.summary?=?summary;??
  64. ????}??
  65. }??

OK,這是第一種解決方案,也是比較簡單常用的一種。

2.使用DataBinding提供的ObservableFields來創建實體類

這種方式使用起來略微麻煩,除了繼承BaseObservable之外,創建屬性的方式也變成下面這種:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. private?final?ObservableField<String>?description?=?new?ObservableField<>();??

屬性的讀寫方式也變了,讀取方式如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. description.get()??

寫入方式如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. this.description.set(description);??

OK,依據上面幾個規則,我新定義的實體類如下:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. /**?
  2. ?*?Created?by?王松?on?2016/7/31.?
  3. ?*/??
  4. public?class?Food?extends?BaseObservable?{??
  5. ????private?final?ObservableField<String>?description?=?new?ObservableField<>();??
  6. ????private?final?ObservableField<String>?img?=?new?ObservableField<>();??
  7. ????private?final?ObservableField<String>?keywords?=?new?ObservableField<>();??
  8. ????private?final?ObservableField<String>?summary?=?new?ObservableField<>();??
  9. ????public?Food()?{??
  10. ????}??
  11. ??
  12. ????public?Food(String?description,?String?img,?String?keywords,?String?summary)?{??
  13. ????????this.description.set(description);??
  14. ????????this.keywords.set(keywords);??
  15. ????????this.img.set(img);??
  16. ????????this.summary.set(summary);??
  17. ????}??
  18. ??
  19. ????@BindingAdapter("bind:img")??
  20. ????public?static?void?loadInternetImage(ImageView?iv,?String?img)?{??
  21. ????????Picasso.with(iv.getContext()).load(img).into(iv);??
  22. ????}??
  23. ??
  24. ????public?void?onItemClick(View?view)?{??
  25. //????????Toast.makeText(view.getContext(),?getDescription(),?Toast.LENGTH_SHORT).show();??
  26. ????????setDescription("111");??
  27. ????}??
  28. ??
  29. ????public?void?clickKeywords(View?view)?{??
  30. ????????Toast.makeText(view.getContext(),?getKeywords(),?Toast.LENGTH_SHORT).show();??
  31. ????}??
  32. ??
  33. ??
  34. ????@Bindable??
  35. ????public?String?getDescription()?{??
  36. ????????return?description.get();??
  37. ????}??
  38. ??
  39. ????public?void?setDescription(String?description)?{??
  40. ????????this.description.set(description);??
  41. ????????notifyPropertyChanged(org.lenve.databinding3.BR.description);??
  42. ????}??
  43. ??
  44. ????public?String?getImg()?{??
  45. ????????return?img.get();??
  46. ????}??
  47. ??
  48. ????public?void?setImg(String?img)?{??
  49. ????????this.img.set(img);??
  50. ????}??
  51. ??
  52. ????public?String?getKeywords()?{??
  53. ????????return?keywords.get();??
  54. ????}??
  55. ??
  56. ????public?void?setKeywords(String?keywords)?{??
  57. ????????this.keywords.set(keywords);??
  58. ????}??
  59. ??
  60. ????public?String?getSummary()?{??
  61. ????????return?summary.get();??
  62. ????}??
  63. ??
  64. ????public?void?setSummary(String?summary)?{??
  65. ????????this.summary.set(summary);??
  66. ????}??
  67. }??

這種方式實現的功能和第一個實體類實現的功能一模一樣。

3.使用DataBinding中提供的集合來存儲數據即可

DataBinding中給我們提供了一些現成的集合,用來存儲數據,比如ObservableArrayList,ObservableArrayMap,因為這些用的少,我這里就不做介紹了。


本文共涉及到三個Demo,由于CSDN對上傳文件大小的限制,我分三次上傳,下載地址如下:


1.http://download.csdn.net/detail/u012702547/9591142

2.http://download.csdn.net/detail/u012702547/9591150

3.http://download.csdn.net/detail/u012702547/9591160


以上。


-------------

更多的Java,Angular,Android,大數據,J2EE,Python,數據庫,Linux,Java架構師,:

http://www.cnblogs.com/zengmiaogen/p/7083694.html



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/538914.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538914.shtml
英文地址,請注明出處:http://en.pswp.cn/news/538914.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

打造一款便攜版的Sublime Text

https://segmentfault.com/a/1190000000707661 https://www.cnblogs.com/52cik/p/sublime-diy.html 直接安裝Sublime Text&#xff0c;不要打開 大家可以參照上文提到的《Sublime Text 全程指引》中的步驟去進行安裝。我這里使用的是Sublime Text 2&#xff0c;其實3也是一樣的…

confluence創建頁面加載緩慢_樹莓派4B使用docker安裝confluence

說明confluence是一個專業的企業知識管理與協同軟件&#xff0c;可以用于構建企業wiki。通過它可以實現團隊成員之間的協作和知識共享。現在大多數公司都會部署一套confluence&#xff0c;用作內部wiki。另外confluence也可以作為個人的知識管理工具來用&#xff0c;只需要花10…

python用map提取一個數的個十百位數_如何使用python中的map函數?

我們在使用python過程中&#xff0c;為了避免錯誤刪除&#xff0c;會選擇做好一個序列后可以插入另外的序列中做為新序列的一部分內容。方便完成一些復雜的工程或多個片段分別編輯后再串成一個完整工程的操作。之前小編向大家介紹了在序列中起到累計作用的reduce函數(https://w…

matlab粒子加速器仿真,粒子群算法優化PID參數 仿真不出結果 程序如下

用的是《MATLAB智能算法30個案例分析》中的程序1.文件名為PSO_PID.mfunction z PSO_PID(x)assignin(base,Kp,x(1)); % 粒子群依次賦值給Kp 這部分運行結果> PSO_PIDassignin(base,Ki,x(2)); …

CentOS5、6的啟動流程

CentOS5/6的啟動流程啟動流程畫了張圖,看著更清晰些: (centos7的啟動流程變化挺大的,這部分待補充)補充(/etc/rc.d/rc.local 不屬于任何服務,為特殊文件,可將不能定義為服務又想開機運行的命令定義在此文件中)添加自定義服務:[rootel5 init.d]# vi /etc/init.d/testsrv #!/bin…

Spark交互式分析平臺Apache Zeppelin的安裝

Zeppelin介紹 Apache Zeppelin提供了web版的類似ipython的notebook&#xff0c;用于做數據分析和可視化。背后可以接入不同的數據處理引擎&#xff0c;包括Spark, Hive, tajo等&#xff0c;原生支持Scala, Java, shell, markdown等。它的整體展現和使用形式和Databricks Cloud是…

win7 php zend,win7系統打開WZend Studio PHP出錯的解決方法

很多朋友安裝win7系統后&#xff0c;在使用的過程中會遇到win7系統打開WZend Studio PHP出錯的情況&#xff0c;可能有很多用戶還是不能自己處理win7系統打開WZend Studio PHP出錯的問題&#xff0c;其實簡單的來說處理win7系統打開WZend Studio PHP出錯的問題只需要按照 1、在…

9個元素換6次達到排序序列_C語言必學的12個排序算法:希爾排序(第3篇)

基本思想希爾排序&#xff08;Shells Sort&#xff09;&#xff0c;以發明人命名&#xff0c;又稱為縮小增量排序&#xff0c;也是一種插入排序算法。主要思想&#xff1a;直接插入排序算法時間和待排數據有關&#xff0c;其平均復雜度是O(n^2)&#xff0c;但是在待排數據已經有…

java快捷鍵禁用_pycharm 掌握這些快捷鍵,你就是大神!!

最重要的快捷鍵1. ctrlshiftA:萬能命令行 2. shift兩次:查看資源文件新建工程第一步操作1. module設置把空包分層去掉,compact empty middle package 2. 設置當前的工程是utf-8,設置的Editor-->File Encodings-->全部改成utf-8,注釋1. ctrl/:單行注釋光標操作1. ctrlalte…

如何在 5 分鐘內讀懂區塊鏈的架構思維?

作為入門者&#xff0c;如何在最短的時間了解區塊鏈技術&#xff0c;區塊鏈思維&#xff0c;以及比特幣的金融原理呢&#xff1f;本文嘗試從比特幣的架構設計思維出發&#xff0c;讓人從宏觀上搞清楚區塊鏈的技術本質。 本文授權轉載自阿里技術 作者 | 鄭吉 區塊鏈不是一種技術…

魅族Flyme5.x以上系統INSTALL_FAILED_SHARED_USER_INCOMPATIBLE

用android studio 連接魅族flyme5.0安裝app&#xff0c;報 Installation error: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE 解決方法&#xff1a; 1、進入手機管家 2、權限管理 3、usb安裝管理 4、關閉 完美解決問題

php取key的value值,獲取數組中key和value的值

方法1&#xff1a;PHP 4 引入了 foreach 結構&#xff0c;和 Perl 以及其他語言很像。這只是一種遍歷數組簡便方法。foreach 僅能用于數組&#xff0c;當試圖將其用于其它數據類型或者一個未初始化的變量時會產生錯誤。有兩種語法&#xff0c;第二種比較次要但卻是第一種的有用…

arduino 上傳項目出錯_Arduino多核編程:簡單例子

不管你是Arduino領域的新手還是經驗豐富的開發人員&#xff0c;很可能你還只使用過單核在進行編程。 這沒有什么好笑的---- 事實上&#xff0c;直到幾天前我才使用Arduino IDE進行了第一次多核編程。 我和所有其他Arduino粉絲都非常喜歡IDE的易用性以及MicroController 開發所需…

Hadoop-RPC應用demo

Hadoop里的rpc框架可以單獨拿出來使用。jar包全在hadoop-common工程里。 導入hadoop-common工程里&#xff08;hadoop-2.7.3為例&#xff09;&#xff1a; hadoop-common-2.7.3.jar \hadoop-2.7.3\share\hadoop\common\lib下的全部jar包 實例 rpc.client 客戶端 rpc.pr…

php 變量 可用拼音表示,php漢字轉拼音的示例

. 代碼如下:class Helper_Spell{public $spellArray array();static public function getArray() {return unserialize(file_get_contents(pytable_without_tune.txt));}/*** desc 獲取字符串的首字母* param $string 要轉換的字符串* param $isOne 是否取首字母* param $uppe…

Opencv-Python:圖像尺寸、圖像的讀取、顯示、保存與復制

Opencv-Python&#xff1a;圖像尺寸、圖像的讀取、顯示、保存與復制 原創 2017年11月23日 21:30:494440在使用opencv的方法時&#xff0c;首先必須導入opencv包。新的opencv導入cv2&#xff0c;這里也和cv做了一個對比 [python] view plaincopy import cv2 一、圖像尺寸 圖像的…

寶塔面板服務器ip地址修改_「網站」快速搭建服務器環境及網站

目錄&#xff1a;「NAS」我的搭建NAS全過程在文章開頭我想說明的是&#xff0c;此文章中所使用的工具為 BT 面板即寶塔面板&#xff0c;適合小白使用但是對于想要提升個人能力來說&#xff0c; BT 面板并不是一個好選擇&#xff0c;而作為新手來說&#xff0c;可以使用該面板進…

redis啟動報錯-磁盤滿了

imjournal: fopen() failed for path: ‘/var/lib/rsyslog/imjournal.state.tmp’: Structure needs cleaning [v8.24.0-57.el7_9.1 try http://www.rsyslog.com/e/2013 ] 1.查看服務狀態 systemctl status rsyslog 2.嘗試重啟服務 systemctl restart rsyslog 3.查看分區占用情…

楊輝三角python_Python面試150題匯總,都是常問的面試題!

周末&#xff0c;Python面試題每日一題暫停更新&#xff0c;下面把最近整理的1-50篇Python面試文整理一下&#xff0c;平時文章都放在比較末尾&#xff0c;閱讀量都不高&#xff0c;相信很多人都沒看過&#xff0c;如果對于Python感興趣的&#xff0c;建議可以認真閱讀一下&…

java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.SCAN_RESULTS flg

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.nokia.wlanapp, PID: 18526java.lang.RuntimeException: Error receiving broadcast Intent { actandroid.net.wifi.SCAN_RESULTS flg0x4000010 (has extras【外部】) } in com.nokia.wlanapp.Receive…