RecyclerView
是一個你們經常使用的列表控件,在列表中難免會出現多種類型的佈局,這時adapter
中多種類型的判斷就會充滿着switch
的壞味道,可怕的是需求變動,增長或修改新的類型時,全部的改動都在adapter
中進行,沒有一個良好的擴展性。MutliItem
主要就是解決這些問題,在正常使用中作到了Adapter
零編碼,解放了複雜的Adapter
類,本庫提供了多類型和ViewHolder
建立綁定的管理器,這樣Adapter
經過依賴倒置與列表中的多類型解耦,還提升了擴展性。在本庫中不一樣實體類能夠直接當成數據源綁定到adapter
中,你不用去擔憂item type
的計算,而且對每種類型的ViewHolder
也作到了隔離。
本庫的定位並非大而全,可是會盡可能作到簡單易用。java
Github地址:MultiItem,請你們多多關注,更多更新會首先在GitHub上體現,也會在第一時間在本平臺發佈android
在Project root
的build.gradle
中添加:git
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}複製代碼
在Module
中添加(最新版本請在源碼地址查看):github
dependencies {
compile 'com.github.free46000:MultiItem:0.9.7'
}複製代碼
這裏因爲單一和多種類型寫法上沒有差異,因此就不單獨貼出單一類型的列表代碼了。
註冊多種類型ViewHolderManager
,併爲adapter
設置多種類型數據源:數組
//初始化adapter
BaseItemAdapter adapter = new BaseItemAdapter();
//爲TextBean數據源註冊ViewHolderManager管理類
adapter.register(TextBean.class, new TextViewManager());
//爲更多數據源註冊ViewHolderManager管理類
adapter.register(ImageTextBean.class, new ImageAndTextManager());
adapter.register(ImageBean.class, new ImageViewManager());
//組裝數據源list
List<Object> list = new ArrayList<>();
list.add(new TextBean("AAA"));
list.add(new ImageBean(R.drawable.img1));
list.add(new ImageTextBean(R.drawable.img2, "BBB" + i));
//爲adapter註冊數據源list
adapter.setDataItems(list);
recyclerView.setAdapter(adapter);複製代碼
ViewHolder
管理類的子類TextViewManager
類,其餘類類似,下面貼出本類所有代碼,是否是很是清晰:bash
public class ImageViewManager extends BaseViewHolderManager<ImageBean> {
@Override
public void onBindViewHolder(BaseViewHolder holder, ImageBean data) {
//在指定viewHolder中獲取控件爲id的view
ImageView imageView = getView(holder, R.id.image);
imageView.setImageResource(data.getImg());
}
@Override
protected int getItemLayoutId() {
//返回item佈局文件id
return R.layout.item_image;
}
}複製代碼
至此本庫的多種類型列表用法已經完成,並無修改或繼承RecyclerView Adapter
類,徹底使用默認實現BaseItemAdapter
便可。maven
這是一種特殊的需求,須要在運行時經過數據源中的某個屬性,判斷加載的佈局,典型的就是聊天功能,相同消息數據對應左右兩種氣泡視圖,在此處貼出註冊時的關鍵代碼,其餘和多種類型列表相似:ide
//初始化adapter
BaseItemAdapter adapter = new BaseItemAdapter();
//爲XXBean數據源註冊XXManager管理類組合
adapter.register(MessageBean.class, new ViewHolderManagerGroup<MessageBean>(new SendMessageManager(), new ReceiveMessageManager()) {
@Override
public int getViewHolderManagerIndex(MessageBean itemData) {
//根據message判斷是否本人發送並返回對應ViewHolderManager的index值
return itemData.getSender().equals(uid) ? 0 : 1;
}
});
recyclerView.setAdapter(adapter);複製代碼
點擊監聽:佈局
adapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(BaseViewHolder viewHolder) {
//經過viewHolder獲取須要的數據
toastUser(String.format("你點擊了第%s位置的數據:%s", viewHolder.getItemPosition()
, viewHolder.getItemData()));
}
});複製代碼
長按監聽:gradle
adapter.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public void onItemLongClick(BaseViewHolder viewHolder) {
//經過viewHolder獲取須要的數據
toastUser(String.format("你長按了第%s位置的數據:%s", viewHolder.getItemPosition()
, viewHolder.getItemData()));
}
});複製代碼
ViewHolderManager
提供視圖建立綁定等工做ItemTypeManager
找到對應的ViewHolderManager
ViewHolder管理源碼類爲ViewHolderManager
,使用者會首先註冊數據源和本實例的對應關係,由類型管理類提供統一管理。
adapter
調用本類方法的時候傳入並作出通用處理ViewHolder
的建立與綁定方法,爲了方便後續使用,寫了一個簡單的BaseViewHolderManager
實現類,請讀者根據業務自行決定是否須要使用更靈活的基類,這裏貼出須要複寫的兩個方法,延續了Adapter
中的命名規則,在使用中減小一些認知成本: /** * 建立ViewHolder * {@link android.support.v7.widget.RecyclerView.Adapter#onCreateViewHolder} */
@NonNull
public abstract V onCreateViewHolder(@NonNull ViewGroup parent);
/** * 爲ViewHolder綁定數據 * {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder} * * @param t 數據源 */
public abstract void onBindViewHolder(@NonNull V holder, @NonNull T t);複製代碼
組合管理源碼類爲ViewHolderManagerGroup
,本實例須要一個ViewHolderManager
集合,並增長經過數據源指定哪一個ViewHolderManager
的方法,使用者一樣會註冊數據源和本實例的對應關係,由類型管理類對本類中的ViewHolderManager
集合進行統一註冊管理。下面貼出關鍵代碼:
private ViewHolderManager[] viewHolderManagers;
/** * @param viewHolderManagers 相同數據源對應的全部ViewHolderManager */
public ViewHolderManagerGroup(ViewHolderManager... viewHolderManagers) {
if (viewHolderManagers == null || viewHolderManagers.length == 0) {
throw new IllegalArgumentException("viewHolderManagers can not be null");
}
this.viewHolderManagers = viewHolderManagers;
}
/** * 根據item數據源中的屬性判斷應該返回的對應viewHolderManagers的index值 * * @param itemData item數據源 * @return index值應該是在viewHolderManagers數組有效範圍內 */
public abstract int getViewHolderManagerIndex(T itemData);複製代碼
類型管理源碼類爲ItemTypeManager
,經過數據源className List
和viewHolderManager List
兩組集合對類型進行管理,並對Adapter
提供註冊和對應關係查找等方法的支持,這裏並無把這個地方設計靈活,若是有一些變化仍是但願能夠在ViewHolderManager
作出適配。
viewHolderManager
時比較簡單,關鍵代碼:/** * 經過數據源`className List`和`viewHolderManager List`兩組集合對類型進行管理 * * @param cls 數據源class * @param manager ViewHolderManager * @see com.freelib.multiitem.adapter.BaseItemAdapter#register(Class, ViewHolderManager) */
public void register(Class<?> cls, ViewHolderManager manager) {
register(getClassName(cls), manager);
}複製代碼
viewHolderManager
時,關鍵代碼:/** * 經過group獲取一組ViewHolderManager循環註冊,並生成不一樣的className做爲標識<br> * 其餘相似{@link #register(Class, ViewHolderManager)} * * @param cls 數據源class * @param group 多個ViewHolderManager的組合 * @see com.freelib.multiitem.adapter.BaseItemAdapter#register(Class, ViewHolderManagerGroup) */
public void register(Class<?> cls, ViewHolderManagerGroup group) {
ViewHolderManager[] managers = group.getViewHolderManagers();
for (int i = 0, length = managers.length; i < length; i++) {
register(getClassNameFromGroup(cls, group, managers[i]), managers[i]);
}
itemClassNameGroupMap.put(getClassName(cls), group);
}複製代碼
但願你們會喜歡,多多留言交流