DataBinding:一行實現花式列表

作者簡介 原創微信公眾號郭霖 WeChat ID: guolin_blog

大家周五好,提前祝大家周末愉快!

本篇來自老司機張旭童投稿,繼續給大家帶來了原創的開源庫。本文是此開源庫系列的第二篇(主要涉及DataBinding),所以文中的上文指系列的第一篇,想從頭了解的朋友可以訪問他的博客查看。

張旭童的博客地址:

http://blog.csdn.net/zxt0601

前言

中,我們利用 Adapter模式 封裝了一個庫,能快速為 任意ViewGroup 添加 子View。有如下特點:

快速簡單使用

支持任意ViewGroup

無耦合

無侵入性

Item支持多種類型

在庫中V1.1.0版本,我也順手加入了 RecyclerView、ListView、GridView 的通用 Adapter 功能,庫地址:

https://github.com/mcxtzhang/all-base-adapter

現在V1.2.0版本發布,我又加入了我最近超愛的一個技術,DataBinding

封裝了一套一行代碼實現花式列表的Adapter。即利用 DataBinding 實現 RecyclerView 中快速使用的 Adapter。

以后不管寫多種type還是單type的列表,利用?DataBinding?和?本庫,都只需要一行代碼!

這里也算是安利 DataBinding 吧,真的超好用。還沒使用的朋友們,在看到本文可以如此簡單寫花式列表后,建議去學習一下。先看用法吧,簡單粗暴到沒朋友。

用法

使用必讀

BaseBindingAdapter?利用 DataBinding 提供的動態綁定技術,使用?BR.data?封裝數據、BR.itemP?封裝點擊事件。所以對?layout 有以下要求:

layout中 數據name 起名data

layout中 點擊事件Presenter 起名 itemP

比如:

1. 單Item列表

效果如圖,順帶演示了 BaseBindingAdapter 封裝的一些增刪功能:


用法:

和其他 BaseAdapter 用法一致

構造函數只需要傳入 context,datas,layout

mAdapter=newBaseBindingAdapter(this, mDatas,R.layout.item_db_single);

好了,列表已經出來了。我不騙你,就這一句話。如果需要設置點擊事件(點擊事件設置所有類型都一樣,下不贅述):

特殊需求:如果有特殊需求,可傳入兩個泛型,重寫onBindViewHolder搞事情:

2. 多Item同種數據類型列表

一般是像IM那種列表,雖然Item不同,但是數據結構是同一個。用法,一句話~效果如圖:


用法:

數據結構(JavaBean)需實現?IBaseMulInterface接口,根據情況返回不同的layout。

構造函數只需要傳入context,datas.

mAdapter=newBaseMulTypeBindingAdapter(this, mDatas);

復雜列表依然一句話:

特殊需求:如果有特殊需求,可傳入數據結構的泛型,避免強轉,重寫?onBindViewHolder()?方法,但是 Binding類 不可避免的需要強轉了:

3. 多Item、多種數據類型列表

各大APP首頁,Banner、列表、推薦混排,數據結構肯定不同,但是依然只要一句代碼搞定Adapter!效果如圖:


用法:

數據結構(JavaBean)需分別實現?IBaseMulInterface接口,返回數據結構對應的layout。

構造函數只需要傳入context,datas.

mAdapter=newBaseMulTypeBindingAdapter(this, mDatas);

特殊需求:如果有特殊需求,重寫?onBindViewHolder()方法,但是 數據結構 和 Binding類 都不可避免的需要強轉了:

4. 不能忘了上文的ViewGroup

上文封裝的 ViewGroup 類型 Adapter 也提供 DataBinding 的支持。當然還是流式布局搭配我自己的側滑菜單控件。效果如圖:


用法:上文一樣,只是 Adapter 換成?SingleBindingAdapter

如果需要設置點擊事件:

mAdapter.setItemPresenter(newItemDelPresenter());

設計思路與實現

使用起來如此爽快,其實寫起來也很簡單。

注意 類BaseBindingAdapter?和?BaseMulTypeBindingAdapter?都不是?abstract?的,這說明我們不需要重寫任何方法

利用 DataBinding,我們在 BasexxxAdapter內部 和 xml 分別做View的創建和數據綁定的工作。

UML類圖

先簡要概括:

BaseBindingVH?繼承自?RecyclerView.ViewHolder,持有?T extends ViewDataBinding類型的?mBinding?變量。利用?ViewDataBinding?我們將不用再寫任何?ViewHolder。

BaseBindingAdapter,繼承自?RecyclerView.Adapter,依賴?BaseBindingVH,onCreateViewHolder(ViewGroup parent, int viewType)方法 返回?BaseBindingVH?作為?ViewHolder。

內部持有三個重要變量:數據對應layout,數據集,Item點擊事件處理類。數據對應layout 會在?onCreateViewHolder(ViewGroup parent, int viewType)?用到。剩下兩個變量在?onBindViewHolder()?用到。對外暴漏?setItemPresenter(Object itemPresenter)供設置點擊事件處理類。

IBaseMulInterface接口 和上文提到的一樣,返回某個數據結構對應的layout,除此之外,本文還有一個十分tricky之處,利用返回的?R.layout.itemxxxx?作為?ItemViewType,在?BaseMulTypeBindingAdapter?會用到。

BaseMulTypeBindingAdapter?繼承自?BaseBindingAdapter,但是它不再關心?mLayoutId?變量,它利用?IBaseMulInterface接口 返回的?R.layout.itemxxxx?作為?ItemViewType,這樣在?onCreateViewHolder(ViewGroup parent, int viewType)?的時候,就可以直接用?viewType?構造出?ItemView。不再依賴?mLayoutId?變量。這是一個我很得意的設計,我在"優雅為RecyclerView增加HeaderView"一文中,也曾用過這個方法。

BaseBindingVH

BaseBindingVH?算是一個核心類,但是又十分簡單。它繼承自?RecyclerView.ViewHolder,持有由泛型傳入的?T extends ViewDataBinding?類型的mBinding變量。

唯一構造函數,需要一個?T t?變量,然后調用?super()?傳入?t.getRoot()?完成?itemView?的賦值。同時對?mBinding?變量賦值。對外暴漏?getBinding()?返回?mBinding?變量。

利用?ViewDataBinding?我們將不用再寫任何?ViewHolder。

BaseBindingAdapter

BaseBindingAdapter,繼承自?RecyclerView.Adapter,依賴?BaseBindingVH,將?BaseBindingVH?作為泛型傳給?RecyclerView.Adapter。

同時?BaseBindingAdapter?本身接受兩個泛型,。

泛型沒有特殊需求可以不傳

泛型D:是Bean類型,如果有就傳。

泛型B:是對應的xml Layout的Binding類

傳入不傳入泛型的區別已經在第二節具體用法里進行了演示,不再贅述。內部持有三個重要變量:

數據對應layout?int mLayoutId;

數據集?List mDatas;

Item點擊事件處理類。Object ItemPresenter;

mLayoutId?和?mDatas?都由構造函數傳入,沒啥好說的。

對外暴漏?setItemPresenter(Object itemPresenter)?供設置點擊事件處理類?ItemPresenter。ItemPresenter?是?Object?類型,這樣才不care你set的Item點擊事件處理類是什么鬼。

onCreateViewHolder(ViewGroup parent, int viewType)?方法返回?BaseBindingVH?作為?ViewHolder。

mLayoutId?會在?onCreateViewHolder(ViewGroup parent, int viewType)?用到,再根據泛型B強轉成對應的?ViewDataBinding:

會在?onBindViewHolder()?方法里,利用 DataBinding 動態綁定?ViewDataBinding.setVariable(BR.itemP, ItemPresenter);為每個Item設置點擊事件。

同時,數據也是同樣在里面綁定的:setVariable(BR.data, mDatas.get(position))。重點代碼如下:

BaseBindingAdapter 內部也封裝了如下方法,方便數據刷新,增刪(定向刷新)調用:

IBaseMulInterface接口

IBaseMulInterface接口 和上文提到的一樣,返回某個數據結構對應的layout.

除此之外,本文還有一個十分tricky之處,利用返回的?R.layout.itemxxxx?作為?ItemViewType,在?BaseMulTypeBindingAdapter?會用到。因為不同的?R.layout.itemxxxx?對于 RecyclerView 來說一定是不同的Item。

BaseMulTypeBindingAdapter

多種ItemType的Base類

BaseMulTypeBindingAdapter?繼承自?BaseBindingAdapter,但是它不再關心?mLayoutId?變量。因此它傳給父類的 泛型B 就是?ViewDataBinding類 本身。解釋如下:

基類的泛型B:不用傳,因為多種 ItemType 肯定 Layout 長得不一樣,那么 Binding類 也不一樣,傳入沒有任何意義

泛型T:多Item 多Bean 情況可以不傳。如果只有一種Bean類型,可以傳入Bean,實現 IBaseMulInterface接口。或者傳入 IBaseMulInterface接口,可以拿到 ?getItemLayoutId(),但是通過 getItemViewType(int position) 一樣。所以多Item多Bean建議不傳。傳入不傳入泛型的區別已經在第二節具體用法里進行了演示,不再贅述。

getItemViewType()?直接返回?IBaseMulInterface接口 的返回值。

在?onCreateViewHolder(ViewGroup parent, int viewType)?的時候,直接用?viewType?構建?ViewDataBinding(ItemView)。不再依賴?mLayoutId?變量。

完整代碼如下:

ViewGroup Adapter的實現

單item

繼承 SingleAdapter,增加 ItemPresenter,在 getView() 完成View創建和綁定。

多Item

更簡單了,繼承 SingleBindingAdapter。重寫getView()即可:

總結

本文利用?DataBinding?的?ViewDataBinding?直接略去寫?ViewHolder。

利用?Object類型 的?ItemPresenter,兼容解決了點擊事件的設置。

最得意的設計,還是利用?R.layout.xxxx?這些布局文件?int類型 的 RID,作為?ItemViewType,一箭雙雕。

DataBinding?很強,希望大家快點擁抱它。

to do list

ViewGroup Adapter 考慮加入復用緩存池

ViewGroup Adapter ,考慮替換onBindView()的ItemView->通用的ViewHolder,這樣可以少寫一些findViewById()代碼

整合 DataBinding 的通用Adapter入庫。(已完成)

完善 RecyclerView、ListView的通用Adapter,支持多種ItemViewType。

加入一些自定義ViewGroup入庫,例如流式布局,九宮格,Banner輪播圖。


完。。。。。。。。。。。。。。。。。。。。。

文章原創作者GuoLin 書籍推薦

郭林大神原創android 書籍:《第一行代碼 android》

淘寶鏈接: https://s.click.taobao.com/t?e=m%3D2%26s%3DgKUfuKdAZKocQipKwQzePOeEDrYVVa64K7Vc7tFgwiHjf2vlNIV67p2n%2BQBNMyE6Rku8%2Bpj6eJall3bs%2B3NRhNHnsKI%2BqxhyM0iVZhTFBom4YIorMPnmg8G0g2OJi%2FzmXHfenomYtn5EW9vzeG8LzfPUwktUBEmkxg5p7bh%2BFbQ%3D&pvid=10_106.6.161.154_3367_1490163222155

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容