Hello大家好,郭老司機(jī)又來了通殃。以前都是看文章的小喵同志摆舟,如今終于體也會到碼字的不易,作為一個(gè)沉默寡言的程序猿邓了,對于碼文無數(shù)的前輩深表敬佩((/- -)/恨诱。
這是歡迎各位踐踏的Github:https://github.com/CarGuo
我叫DEMO:https://github.com/CarGuo/LazyRecyclerAdapter
RecylerView相信大家都聽過(你確定要說沒聽過 = =),在ListView橫行的年代里骗炉,RecyclerView攜帶了褒貶不一的評價(jià)照宝,開始進(jìn)入了我們的視線,那時(shí)候剛好開始了新的項(xiàng)目句葵,正好就拿它練手了厕鹃。下方進(jìn)入介紹使用流程,建議對著Demo擼起來乍丈。( ??-?? )
正常情況下剂碴,對于每一個(gè)不同的列表,我們經(jīng)常需要實(shí)現(xiàn)不同的Adapter 轻专,來處理對應(yīng)的邏輯忆矛,這樣導(dǎo)致了我們有著許多重復(fù)的代碼,在優(yōu)化代碼(懶)這種動(dòng)力的驅(qū)動(dòng)下请垛,個(gè)人實(shí)現(xiàn)了一個(gè)通用的Adapter催训。后面所說的Holder,可以理解為列表中一個(gè)Item宗收,屬于它的邏輯處理類漫拭,每一種類型的Item有一種Holder。
只需要一個(gè)Adapter混稽,你就可以實(shí)現(xiàn)各種類型的列表采驻,在一個(gè)列表里兼容不同類型的Item,你需要做的匈勋,僅僅是維護(hù)你的Holder(類似List里的一個(gè)Item)和Model礼旅,無需再關(guān)心其他,實(shí)現(xiàn)高復(fù)用與多樣式邏輯颓影,外帶支持自定義動(dòng)畫各淀,多種上下拉實(shí)現(xiàn)方式,不需要再寫任何Adapter代碼(o)/诡挂。
1碎浇、 CommonRecyclerManager :綁定layoutId和你的Holder類名。
這個(gè)管理類是用于綁定Holder和R.layout.xxx璃俗,這樣在后面CommonRecyclerAdapter 用它通過數(shù)據(jù)Model的layoutId奴璃,找到對應(yīng)的Holder并創(chuàng)建它。
//將布局的ID和holder類型關(guān)聯(lián)
commonRecyclerManager.addType(TextHolder.ID, TextHolder.class.getName());
2城豁、 RecyclerBaseHolder :繼承這個(gè)Holder苟穆,實(shí)現(xiàn)你的需求。
RecyclerBaseHolder的所有Holder的基類唱星,他繼承了RecyclerView.ViewHolder雳旅,并定義寫兩個(gè)方法,所以你繼承它就對了间聊,在createView的時(shí)候找到控件攒盈,在onBind讀取數(shù)據(jù)填充畫面。這里就是實(shí)現(xiàn)你夢想的地方哎榴!
//實(shí)現(xiàn)的hodler繼承RecyclerBaseHolder型豁,重載下面方式實(shí)現(xiàn)你的需求
public class TextHolder extends RecyclerBaseHolder {
//布局id,一般我習(xí)慣吧這個(gè)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創(chuàng)建好了
@Override
public void createView(View v) {
ButterKnife.bind(this, v);
}
//view創(chuàng)建好了迎变,更具數(shù)據(jù)處理邏輯
@Override
public void onBind(RecyclerBaseModel model, int position) {
//轉(zhuǎn)化為你的model
TextModel textModel = (TextModel) (model);
itemText.setText(textModel.getText());
}
//不需要可以不寫
@Override
public AnimatorSet getAnimator(View view) {
//實(shí)現(xiàn)你的動(dòng)畫
return null;
}
}
3、 CommonRecyclerAdapter :通用的適配器
只需要傳入數(shù)據(jù)List和CommonRecyclerManager飘言,就會根據(jù)Model的順序衣形,通過數(shù)據(jù)的layoutId,在RecyclerView中自動(dòng)生成對應(yīng)的Holder姿鸿,其他的功能只需要簡單的配置即可泵喘。
//用數(shù)據(jù)和manager創(chuàng)建
adapteradapter = new CommonRecyclerAdapter(getActivity(), commonRecyclerManager, datas);
//支持需要加載更多
adapter.setNeedLoadMore(true);
//支持空數(shù)據(jù)顯示 空頁面
adapter.setShowNoData(true);
//設(shè)置item顯示動(dòng)畫支持打開
adapter.setNeedAnimation(true);
4、RecyclerBaseModel :數(shù)據(jù)model的積累般妙,必須繼承它纪铺,不離不棄。
繼承它的作用是碟渺,因?yàn)檎麄€(gè)Adapter都是以它為基類鲜锚,你需要繼承他,最終的是苫拍,你需要這個(gè)Model對應(yīng)的布局Id芜繁,這樣它才能找到屬于自己的Holder。
//繼承RecyclerBaseModel實(shí)現(xiàn)你需要的數(shù)據(jù)類型
public class TextModel extends RecyclerBaseModel {
private String text = "";
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
總結(jié)起來就是
1绒极、實(shí)現(xiàn)你的Holder并繼承RecyclerBaseHolder骏令,這里是你實(shí)現(xiàn)需求的地方,相當(dāng)于Item的邏輯垄提。
2榔袋、讓你的數(shù)據(jù)model繼承RecyclerBaseModel周拐,設(shè)置Model的LayoutId(很重要),這樣model就會通過CommonRecyclerManager凰兑,找到LayoutId對應(yīng)關(guān)聯(lián)的Holder妥粟,并生成它。
3吏够、你需要一個(gè)CommonRecyclerManager來綁定你的LayoutId和處理這布局的Holder類名勾给。
4、通過CommonRecyclerManager和Model的數(shù)據(jù)列表生成CommonRecyclerAdapter锅知。
5播急、把Adapter交給Recycler。
邏輯看起來是不是有些復(fù)雜售睹?其實(shí)就是model的LayoutId桩警,CommonRecyclerManager通過關(guān)聯(lián)了處理它的Holder。這樣我們只需要在數(shù)據(jù)List里侣姆,根據(jù)數(shù)據(jù)設(shè)置不同的LayoutId的model生真,Adapter就會自動(dòng)匹配對應(yīng)的Holder。
如此一來捺宗,<( ̄︶ ̄)>你只需要實(shí)現(xiàn)好Holder和組裝好Model柱蟀,任何列表都可以使用起來,不需要再寫Adapter邏輯了蚜厉。根據(jù)model的順序长已,Adapter自動(dòng)生成對應(yīng)的Holder,并且同一個(gè)Holder是可以綁定不同的LayoutId昼牛,以后你只需要維護(hù)和兼容你的Holder术瓮,在各個(gè)列表里通用的你holder邏輯了,是不是瞬間代碼干凈了好多贰健?
下拉刷新與上拉加載更多
普通的列表胞四,直接使用系統(tǒng)的SwipeRefreshLayout就可以啦,簡單有好用伶椿。下拉加載更多直接添加下方方法辜伟,輕松實(shí)現(xiàn)上下拉刷新<( ̄︶ ̄),簡單粗暴脊另,就是記得要加個(gè)鎖避免重復(fù)進(jìn)入导狡。
//打開支持需要加載更多
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);
}
}
//當(dāng)前第一個(gè)可視的是哪個(gè)item
@Override
public void onScrolled(int firstPosition) {
}
});
其他配置
你還可以配置是否顯示動(dòng)畫效果,配置上拉loading的顏色偎痛,單擊和長按等旱捧,看下面。
//支持空數(shù)據(jù)顯示 空頁面
adapter.setShowNoData(true);
//顯示空數(shù)據(jù)model,不設(shè)置顯示默認(rèn)空頁面
adapter.setNoDataModel(noDataModel);
//顯示空數(shù)據(jù)頁面布局,不設(shè)置顯示默認(rèn)踩麦,布局id需要通過CommonRecyclerManager關(guān)聯(lián)hodler
adapter.setNoDataLayoutId(noDataLayoutId);
//設(shè)置動(dòng)畫支持打開
adapter.setNeedAnimation(true);
//添加點(diǎn)擊
adapter.setOnItemClickListener();
XRecyclerView兼容支持
這里添加了XRecyclerView枚赡,并且對其進(jìn)行了修改氓癌。XRecyclerView內(nèi)置了內(nèi)部Adapter,使其支持添加頭部标锄,自帶上下拉效果的控件顽铸,部分調(diào)整之后茁计,全面支持CommonRecyclerAdapter料皇。
不需要監(jiān)聽滑動(dòng),不需要SwipeRefreshLayout星压,輕松添加刷新與加載更多践剂。而且更是支持動(dòng)態(tài)配置,上下拉的各種樣式支持娜膘,具體在ProgressStyle下有多種類型支持配置逊脯,解決了Adapter對瀑布流上拉的支持不夠兼容的問題。
這里使用方式竣贪,和普通的RecyclerView一樣军洼,支持和CommonRecyclerAdapter的配合,而且它同樣支持空頁面顯示演怎,還支持添加各種頭部匕争,唯一需要注意的是,添加分割線類addItemDecoration和點(diǎn)擊的時(shí)候爷耀,需要針對添加了頭部甘桑,和刷新的絕對的position,換算成相對的位置歹叮,此處曾經(jīng)把自己坑哭了╥﹏╥...跑杭,下面看代碼吧。
//是否屏蔽下拉
//xRecycler.setPullRefreshEnabled(false);
//上拉加載更多樣式咆耿,也可以設(shè)置下拉
xRecycler.setLoadingMoreProgressStyle(ProgressStyle.SysProgress);
//設(shè)置管理器德谅,關(guān)聯(lián)布局與holder類名,不同id可以管理一個(gè)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);
//本身也支持設(shè)置空局部
//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的數(shù)量
Toast.makeText(getActivity(), "點(diǎn)擊了H荨窄做! " + (position - 2), Toast.LENGTH_SHORT).show();
}
});
最后
到這里你已經(jīng)知道了大致的用法了吧。詳細(xì)的內(nèi)部實(shí)現(xiàn)屑迂,可以通過DEMO查看浸策。大致邏輯是 CommonRecyclerManager 關(guān)聯(lián)接layoutId和Holder類名,CommonRecyclerAdapter通過Model的layoutId找到這個(gè)Holder惹盼,然后用layoutId創(chuàng)建view庸汗,把View、position手报、model傳入到Holder里面實(shí)現(xiàn)數(shù)據(jù)填充蚯舱。所layoutId也是類型id*改化,注意:
使用的時(shí)候切記要給你的model設(shè)置setResLayoutId(),這是最容易讓人遺忘的。
我叫DEMO:https://github.com/CarGuo/LazyRecyclerAdapter