通用RecylerAdapter绳慎,內(nèi)置XRecyclerView纵竖,兼容上下拉與動(dòng)畫漠烧,高復(fù)用,一個(gè)Adapter通用所有頁面靡砌,支持空頁面已脓,懶人專屬

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è)列表多種類型的item

正常情況下剂碴,對于每一個(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ù)ModellayoutId奴璃,找到對應(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ù)ListCommonRecyclerManager飘言,就會根據(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。

效果GIF

如此一來捺宗,<( ̄︶ ̄)>你只需要實(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

看明白了嗎枉昏?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陈肛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兄裂,更是在濱河造成了極大的恐慌句旱,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晰奖,死亡現(xiàn)場離奇詭異谈撒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)匾南,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門啃匿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛆楞,你說我怎么就攤上這事溯乒。” “怎么了豹爹?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵裆悄,是天一觀的道長。 經(jīng)常有香客問我帅戒,道長灯帮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任逻住,我火速辦了婚禮钟哥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞎访。我一直安慰自己腻贰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布扒秸。 她就那樣靜靜地躺著播演,像睡著了一般。 火紅的嫁衣襯著肌膚如雪伴奥。 梳的紋絲不亂的頭發(fā)上写烤,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機(jī)與錄音拾徙,去河邊找鬼洲炊。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暂衡。 我是一名探鬼主播询微,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼狂巢!你這毒婦竟也來了撑毛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤唧领,失蹤者是張志新(化名)和其女友劉穎藻雌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疹吃,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹦疑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年西雀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萨驶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡艇肴,死狀恐怖腔呜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情再悼,我是刑警寧澤核畴,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站冲九,受9級特大地震影響谤草,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜莺奸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一丑孩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧灭贷,春花似錦温学、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至览妖,卻和暖如春轧拄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讽膏。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工檩电, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓是嗜,卻偏偏與公主長得像愈案,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子鹅搪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容