這是歡迎各位踐踏的Github:github.com/CarGuojavascript
我叫DEMO:github.com/CarGuo/Lazy…java
RecylerView相信你們都聽過(你肯定要說沒聽過 = =),在ListView橫行的年代裏,RecyclerView攜帶了褒貶不一的評價,開始進入了咱們的視線,那時候恰好開始了新的項目,正好就拿它練手了。下方進入介紹使用流程,建議對着Demo擼起來。( ・᷄-・᷅ )git
正常狀況下,對於每個不一樣的列表,咱們常常須要實現不一樣的Adapter ,來處理對應的邏輯,這樣致使了咱們有着許多重複的代碼,在優化代碼(懶)這種動力的驅動下,我的實現了一個通用的Adapter。後面所說的Holder,能夠理解爲列表中一個Item,屬於它的邏輯處理類,每一種類型的Item有一種Holder。github
只須要一個Adapter,你就能夠實現各類類型的列表,在一個列表裏兼容不一樣類型的Item,你須要作的,僅僅是維護你的Holder(相似List裏的一個Item)和Model,無需再關心其餘,實現高複用與多樣式邏輯,外帶支持自定義動畫,多種上下拉實現方式,不須要再寫任何Adapter代碼(^o^)/。api
一、 CommonRecyclerManager :綁定layoutId和你的Holder類名。
這個管理類是用於綁定Holder和R.layout.xxx,這樣在後面CommonRecyclerAdapter 用它經過數據Model的layoutId,找到對應的Holder並建立它。ide
//將佈局的ID和holder類型關聯
commonRecyclerManager.addType(TextHolder.ID, TextHolder.class.getName());複製代碼
二、 RecyclerBaseHolder :繼承這個Holder,實現你的需求。
RecyclerBaseHolder的全部Holder的基類,他繼承了RecyclerView.ViewHolder,並定義寫兩個方法,因此你繼承它就對了,在createView的時候找到控件,在onBind讀取數據填充畫面。這裏就是實現你夢想的地方!佈局
//實現的hodler繼承RecyclerBaseHolder,重載下面方式實現你的需求
public class TextHolder extends RecyclerBaseHolder {
//佈局id,通常我習慣吧這個Holder須要處理的id都寫在這裏,方便管理
public final static int ID = R.layout.text_item;
@BindView(R.id.item_text)
TextView itemText;
public TextHolder(Context context, View v) {
super(context, v);
}
//view建立好了
@Override
public void createView(View v) {
ButterKnife.bind(this, v);
}
//view建立好了,更具數據處理邏輯
@Override
public void onBind(RecyclerBaseModel model, int position) {
//轉化爲你的model
TextModel textModel = (TextModel) (model);
itemText.setText(textModel.getText());
}
//不須要能夠不寫
@Override
public AnimatorSet getAnimator(View view) {
//實現你的動畫
return null;
}
}複製代碼
三、 CommonRecyclerAdapter :通用的適配器
只須要傳入數據List和CommonRecyclerManager,就會根據Model的順序,經過數據的layoutId,在RecyclerView中自動生成對應的Holder,其餘的功能只須要簡單的配置便可。post
//用數據和manager建立
adapteradapter = new CommonRecyclerAdapter(getActivity(), commonRecyclerManager, datas);
//支持須要加載更多
adapter.setNeedLoadMore(true);
//支持空數據顯示 空頁面
adapter.setShowNoData(true);
//設置item顯示動畫支持打開
adapter.setNeedAnimation(true);複製代碼
四、RecyclerBaseModel :數據model的積累,必須繼承它,不離不棄。
繼承它的做用是,由於整個Adapter都是以它爲基類,你須要繼承他,最終的是,你須要這個Model對應的佈局Id,這樣它才能找到屬於本身的Holder。優化
//繼承RecyclerBaseModel實現你須要的數據類型
public class TextModel extends RecyclerBaseModel {
private String text = "";
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}複製代碼
一、實現你的Holder並繼承RecyclerBaseHolder,這裏是你實現需求的地方,至關於Item的邏輯。動畫
二、讓你的數據model繼承RecyclerBaseModel,設置Model的LayoutId(很重要),這樣model就會經過CommonRecyclerManager,找到LayoutId對應關聯的Holder,並生成它。
三、你須要一個CommonRecyclerManager來綁定你的LayoutId和處理這佈局的Holder類名。
四、經過CommonRecyclerManager和Model的數據列表生成CommonRecyclerAdapter。
五、把Adapter交給Recycler。
邏輯看起來是否是有些複雜?其實就是model的LayoutId,CommonRecyclerManager經過關聯了處理它的Holder。這樣咱們只須要在數據List裏,根據數據設置不一樣的LayoutId的model,Adapter就會自動匹配對應的Holder。
如此一來,<( ̄︶ ̄)>你只須要實現好Holder和組裝好Model,任何列表均可以使用起來,不須要再寫Adapter邏輯了。根據model的順序,Adapter自動生成對應的Holder,而且同一個Holder是能夠綁定不一樣的LayoutId,之後你只須要維護和兼容你的Holder,在各個列表裏通用的你holder邏輯了,是否是瞬間代碼乾淨了好多?
普通的列表,直接使用系統的SwipeRefreshLayout就能夠啦,簡單有好用。下拉加載更多直接添加下方方法,輕鬆實現上下拉刷新<( ̄︶ ̄),簡單粗暴,就是記得要加個鎖避免重複進入。
//打開支持須要加載更多
adapter.setNeedLoadMore(true);
recycler.addOnScrollListener(new LoadMoreScrollListener() {
@Override
public void onLoadMore() {
//注意加鎖
if (!isLoadMore) {
isLoadMore = true;
recycler.postDelayed(new Runnable() {
@Override
public void run() {
isLoadMore = false;
loadMore();
}
}, 2000);
}
}
//當前第一個可視的是哪一個item
@Override
public void onScrolled(int firstPosition) {
}
});複製代碼
你還能夠配置是否顯示動畫效果,配置上拉loading的顏色,單擊和長按等,看下面。
//支持空數據顯示 空頁面
adapter.setShowNoData(true);
//顯示空數據model,不設置顯示默認空頁面
adapter.setNoDataModel(noDataModel);
//顯示空數據頁面佈局,不設置顯示默認,佈局id須要經過CommonRecyclerManager關聯hodler
adapter.setNoDataLayoutId(noDataLayoutId);
//設置動畫支持打開
adapter.setNeedAnimation(true);
//添加點擊
adapter.setOnItemClickListener();複製代碼
這裏添加了XRecyclerView,而且對其進行了修改。XRecyclerView內置了內部Adapter,使其支持添加頭部,自帶上下拉效果的控件,部分調整以後,全面支持CommonRecyclerAdapter。
不須要監聽滑動,不須要SwipeRefreshLayout,輕鬆添加刷新與加載更多。並且更是支持動態配置,上下拉的各類樣式支持,具體在ProgressStyle下有多種類型支持配置,解決了Adapter對瀑布流上拉的支持不夠兼容的問題。
這裏使用方式,和普通的RecyclerView同樣,支持和CommonRecyclerAdapter的配合,並且它一樣支持空頁面顯示,還支持添加各類頭部,惟一須要注意的是,添加分割線類addItemDecoration和點擊的時候,須要針對添加了頭部,和刷新的絕對的position,換算成相對的位置,此處曾經把本身坑哭了╥﹏╥...,下面看代碼吧。
//是否屏蔽下拉
//xRecycler.setPullRefreshEnabled(false);
//上拉加載更多樣式,也能夠設置下拉
xRecycler.setLoadingMoreProgressStyle(ProgressStyle.SysProgress);
//設置管理器,關聯佈局與holder類名,不一樣id能夠管理一個holder
CommonRecyclerManager commonRecyclerManager = new CommonRecyclerManager();
commonRecyclerManager.addType(ImageHolder.ID, ImageHolder.class.getName());
commonRecyclerManager.addType(TextHolder.ID, TextHolder.class.getName());
commonRecyclerManager.addType(ClickHolder.ID, ClickHolder.class.getName());
//初始化通用管理器
commonRecyclerAdapter = new CommonRecyclerAdapter(getActivity(), commonRecyclerManager, dataList);
xRecycler.setAdapter(commonRecyclerAdapter);
ImageView imageView = new ImageView(getActivity());
imageView.setImageResource(R.drawable.xxx1);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setMinimumHeight(dip2px(getActivity(), 100));
//添加頭部
xRecycler.addHeaderView(imageView);
//自己也支持設置空局部
//xRecycler.setEmptyView();
xRecycler.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
xRecycler.postDelayed(new Runnable() {
@Override
public void run() {
xRecycler.refreshComplete();
}
}, 2000);
}
@Override
public void onLoadMore() {
xRecycler.postDelayed(new Runnable() {
@Override
public void run() {
loadMore();
}
}, 2000);
}
});
commonRecyclerAdapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(Context context, int position) {
//須要減去你的header和刷新的view的數量
Toast.makeText(getActivity(), "點擊了!! " + (position - 2), Toast.LENGTH_SHORT).show();
}
});複製代碼
到這裏你已經知道了大體的用法了吧。詳細的內部實現,能夠經過DEMO查看。大體邏輯是 CommonRecyclerManager 關聯接layoutId和Holder類名,CommonRecyclerAdapter經過Model的layoutId找到這個Holder,而後用layoutId建立view,把View、position、model傳入到Holder裏面實現數據填充。所layoutId也是*類型id,注意:
使用的時候切記要給你的model設置setResLayoutId(),這是最容易讓人遺忘的。
我叫DEMO:github.com/CarGuo/Lazy…