成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

RecyclerView實(shí)現(xiàn)多type頁(yè)面

testHs / 1634人閱讀

摘要:,無(wú)法復(fù)用,假如有多個(gè)頁(yè)面有多個(gè),那么就要寫(xiě)多個(gè)。綁定,主要作用是綁定數(shù)據(jù)到正確的視圖上??删S護(hù)性不同的列表類(lèi)型由添加處理,哪怕添加多個(gè),相互之間互不干擾,代碼簡(jiǎn)潔,維護(hù)成本低。

目錄介紹

01.先看看實(shí)際需求

02.adapter實(shí)現(xiàn)多個(gè)type

03.這樣寫(xiě)的弊端

04.如何優(yōu)雅實(shí)現(xiàn)adapter封裝

好消息

博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識(shí)點(diǎn),Android技術(shù)博客,Python學(xué)習(xí)筆記等等,還包括平時(shí)開(kāi)發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題,長(zhǎng)期更新維護(hù)并且修正,持續(xù)完善……開(kāi)源的文件是markdown格式的!同時(shí)也開(kāi)源了生活博客,從12年起,積累共計(jì)N篇[近100萬(wàn)字,陸續(xù)搬到網(wǎng)上],轉(zhuǎn)載請(qǐng)注明出處,謝謝!

鏈接地址:https://github.com/yangchong2...

如果覺(jué)得好,可以star一下,謝謝!當(dāng)然也歡迎提出建議,萬(wàn)事起于忽微,量變引起質(zhì)變!

01.先看看實(shí)際需求

比如一個(gè)APP的首頁(yè),包含Banner區(qū)、廣告區(qū)、文本內(nèi)容、圖片內(nèi)容、新聞內(nèi)容等等。

RecyclerView 可以用ViewType來(lái)區(qū)分不同的item,也可以滿足需求,但還是存在一些問(wèn)題,比如:

1,在item過(guò)多邏輯復(fù)雜列表界面,Adapter里面的代碼量龐大,邏輯復(fù)雜,后期難以維護(hù)。

2,每次增加一個(gè)列表都需要增加一個(gè)Adapter,重復(fù)搬磚,效率低下。

3,無(wú)法復(fù)用adapter,假如有多個(gè)頁(yè)面有多個(gè)type,那么就要寫(xiě)多個(gè)adapter。

4,要是有局部刷新,那么就比較麻煩了,比如廣告區(qū)也是一個(gè)九宮格的RecyclerView,點(diǎn)擊局部刷新當(dāng)前數(shù)據(jù),比較麻煩。

02.adapter實(shí)現(xiàn)多個(gè)type

通常寫(xiě)一個(gè)多Item列表的方法

根據(jù)不同的ViewType 處理不同的item,如果邏輯復(fù)雜,這個(gè)類(lèi)的代碼量是很龐大的。如果版本迭代添加新的需求,修改代碼很麻煩,后期維護(hù)困難。

主要操作步驟

在onCreateViewHolder中根據(jù)viewType參數(shù),也就是getItemViewType的返回值來(lái)判斷需要?jiǎng)?chuàng)建的ViewHolder類(lèi)型

在onBindViewHolder方法中對(duì)ViewHolder的具體類(lèi)型進(jìn)行判斷,分別為不同類(lèi)型的ViewHolder進(jìn)行綁定數(shù)據(jù)與邏輯處理

代碼如下所示

public class HomePageAdapter extends RecyclerView.Adapter {
    public static final int TYPE_BANNER = 0;
    public static final int TYPE_AD = 1;
public static final int TYPE_TEXT = 2;
    public static final int TYPE_IMAGE = 3;
    public static final int TYPE_NEW = 4;
    private List mData;

    public void setData(List data) {
        mData = data;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType){
            case TYPE_BANNER:
                return new BannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.home_banner_layout,null));
            case TYPE_AD:
                return new BannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.home_ad_item_layout,null));
            case TYPE_TEXT:
                return new BannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.home_text_item_layout,null));
            case TYPE_IMAGE:
                return new BannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.home_image_item_layout,null));
            case TYPE_NEW:
                return new BannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.home_news_item_layout,null));
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int type = getItemViewType(position);
        switch (type){
            case TYPE_BANNER:
                // banner 邏輯處理
                break;
            case TYPE_AD:
                // 廣告邏輯處理
                break;
            case TYPE_TEXT:
                // 文本邏輯處理
                break;
            case TYPE_IMAGE:
               //圖片邏輯處理
                break;
            case TYPE_NEW:
                //視頻邏輯處理
                break;
            // ... 此處省去N行代碼
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(position == 0){
            return TYPE_BANNER;//banner在開(kāi)頭
        }else {
            return mData.get(position).type;//type 的值為T(mén)YPE_AD,TYPE_IMAGE,TYPE_AD,等其中一個(gè)
        }

    }

    @Override
    public int getItemCount() {
        return mData == null ? 0:mData.size();
    }



    public static class BannerViewHolder extends RecyclerView.ViewHolder{

        public BannerViewHolder(View itemView) {
            super(itemView);
            //綁定控件
        }
    }

    public static class NewViewHolder extends RecyclerView.ViewHolder{

        public VideoViewHolder(View itemView) {
            super(itemView);
            //綁定控件
        }
    }
    public static class AdViewHolder extends RecyclerView.ViewHolder{

        public AdViewHolder(View itemView) {
            super(itemView);
            //綁定控件
        }
    }
    public static class TextViewHolder extends RecyclerView.ViewHolder{

        public TextViewHolder(View itemView) {
            super(itemView);
            //綁定控件
        }
    }
    public static class ImageViewHolder extends RecyclerView.ViewHolder{

        public ImageViewHolder(View itemView) {
            super(itemView);
            //綁定控件
        }
    }
}

03.這樣寫(xiě)的弊端

上面那樣寫(xiě)的弊端

類(lèi)型檢查與類(lèi)型轉(zhuǎn)型,由于在onCreateViewHolder根據(jù)不同類(lèi)型創(chuàng)建了不同的ViewHolder,所以在onBindViewHolder需要針對(duì)不同類(lèi)型的ViewHolder進(jìn)行數(shù)據(jù)綁定與邏輯處理,這導(dǎo)致需要通過(guò)instanceof對(duì)ViewHolder進(jìn)行類(lèi)型檢查與類(lèi)型轉(zhuǎn)型。

不利于擴(kuò)展,目前的需求是列表中存在5種布局類(lèi)類(lèi)型,那么如果需求變動(dòng),極端一點(diǎn)的情況就是數(shù)據(jù)源是從服務(wù)器獲取的,數(shù)據(jù)中的model決定列表中的布局類(lèi)型。這種情況下,每當(dāng)model改變或model類(lèi)型增加,我們都要去改變adapter中很多的代碼,同時(shí)Adapter還必須知道特定的model在列表中的位置(position)除非跟服務(wù)端約定好,model(位置)不變,很顯然,這是不現(xiàn)實(shí)的。

不利于維護(hù),這點(diǎn)應(yīng)該是上一點(diǎn)的延伸,隨著列表中布局類(lèi)型的增加與變更,getItemViewType、onCreateViewHolder、onBindViewHolder中的代碼都需要變更或增加,Adapter 中的代碼會(huì)變得臃腫與混亂,增加了代碼的維護(hù)成本。

04.如何優(yōu)雅實(shí)現(xiàn)adapter封裝

核心目的就是三個(gè)

避免類(lèi)的類(lèi)型檢查與類(lèi)型轉(zhuǎn)型

增強(qiáng)Adapter的擴(kuò)展性

增強(qiáng)Adapter的可維護(hù)性

當(dāng)列表中類(lèi)型增加或減少時(shí)Adapter中主要改動(dòng)的就是getItemViewType、onCreateViewHolder、onBindViewHolder這三個(gè)方法,因此,我們就從這三個(gè)方法中開(kāi)始著手。

既然可能存在多個(gè)type類(lèi)型的view,那么能不能把這些比如banner,廣告,文本,視頻,新聞等當(dāng)做一個(gè)HeaderView來(lái)操作。

在getItemViewType方法中。

減少if之類(lèi)的邏輯判斷簡(jiǎn)化代碼,可以簡(jiǎn)單粗暴的用hashCode作為增加type標(biāo)識(shí)。

通過(guò)創(chuàng)建列表的布局類(lèi)型,同時(shí)返回的不再是簡(jiǎn)單的布局類(lèi)型標(biāo)識(shí),而是布局的hashCode值

private ArrayList headers = new ArrayList<>();
    
public interface InterItemView {

    /**
     * 創(chuàng)建view
     * @param parent            parent
     * @return                  view
     */
    View onCreateView(ViewGroup parent);
    
    /**
     * 綁定view
     * @param headerView        headerView
     */
    void onBindView(View headerView);
}
    
/**
 * 獲取類(lèi)型,主要作用是用來(lái)獲取當(dāng)前項(xiàng)Item(position參數(shù))是哪種類(lèi)型的布局
 * @param position                      索引
 * @return                              int
 */
@Deprecated
@Override
public final int getItemViewType(int position) {
    if (headers.size()!=0){
        if (position= 0){
            return footers.get(i).hashCode();
        }
    }
    return getViewType(position-headers.size());
}

onCreateViewHolder

getItemViewType返回的是布局hashCode值,也就是onCreateViewHolder(ViewGroup parent, int viewType)參數(shù)中的viewType

/**
 * 創(chuàng)建viewHolder,主要作用是創(chuàng)建Item視圖,并返回相應(yīng)的ViewHolder
 * @param parent                        parent
 * @param viewType                      type類(lèi)型
 * @return                              返回viewHolder
 */
@NonNull
@Override
public final BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = createViewByType(parent, viewType);
    if (view!=null){
        return new BaseViewHolder(view);
    }
    final BaseViewHolder viewHolder = OnCreateViewHolder(parent, viewType);
    setOnClickListener(viewHolder);
    return viewHolder;
}

private View createViewByType(ViewGroup parent, int viewType){
    for (InterItemView headerView : headers){
        if (headerView.hashCode() == viewType){
            View view = headerView.onCreateView(parent);
            StaggeredGridLayoutManager.LayoutParams layoutParams;
            if (view.getLayoutParams()!=null) {
                layoutParams = new StaggeredGridLayoutManager.LayoutParams(view.getLayoutParams());
            } else {
                layoutParams = new StaggeredGridLayoutManager.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            }
            layoutParams.setFullSpan(true);
            view.setLayoutParams(layoutParams);
            return view;
        }
    }
    for (InterItemView footerView : footers){
        if (footerView.hashCode() == viewType){
            View view = footerView.onCreateView(parent);
            StaggeredGridLayoutManager.LayoutParams layoutParams;
            if (view.getLayoutParams()!=null) {
                layoutParams = new StaggeredGridLayoutManager.LayoutParams(view.getLayoutParams());
            } else {
                layoutParams = new StaggeredGridLayoutManager.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            }
            layoutParams.setFullSpan(true);
            view.setLayoutParams(layoutParams);
            return view;
        }
    }
    return null;
}

在onBindViewHolder方法中??梢钥吹?,在此方法中,添加一種header類(lèi)型的view,則通過(guò)onBindView進(jìn)行數(shù)據(jù)綁定。

/**
 * 綁定viewHolder,主要作用是綁定數(shù)據(jù)到正確的Item視圖上。當(dāng)視圖從不可見(jiàn)到可見(jiàn)的時(shí)候,會(huì)調(diào)用這個(gè)方法。
 * @param holder                        holder

 */
@Override
public final void onBindViewHolder(BaseViewHolder holder, int position) {
    holder.itemView.setId(position);
    if (headers.size()!=0 && position=0){
        footers.get(i).onBindView(holder.itemView);
        return ;
    }
    OnBindViewHolder(holder,position-headers.size());
}
```

如何使用,如下所示,這個(gè)就是banner類(lèi)型,可以說(shuō)是解耦了之前adapter中復(fù)雜的操作

InterItemView interItemView = new InterItemView() {
    @Override
    public View onCreateView(ViewGroup parent) {
        BannerView header = new BannerView(HeaderFooterActivity.this);
        header.setHintView(new ColorPointHintView(HeaderFooterActivity.this,
                Color.YELLOW, Color.GRAY));
        header.setHintPadding(0, 0, 0, (int) AppUtils.convertDpToPixel(
                8, HeaderFooterActivity.this));
        header.setPlayDelay(2000);
        header.setLayoutParams(new RecyclerView.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                (int) AppUtils.convertDpToPixel(200, HeaderFooterActivity.this)));
        header.setAdapter(new BannerAdapter(HeaderFooterActivity.this));
        return header;
    }

    @Override
    public void onBindView(View headerView) {

    }
};
adapter.addHeader(interItemView);

封裝后好處

拓展性——Adapter并不關(guān)心不同的列表類(lèi)型在列表中的位置,因此對(duì)于Adapter來(lái)說(shuō)列表類(lèi)型可以隨意增加或減少。十分方便,同時(shí)設(shè)置類(lèi)型view的布局和數(shù)據(jù)綁定都不需要在adapter中處理。充分解耦。

可維護(hù)性——不同的列表類(lèi)型由adapter添加headerView處理,哪怕添加多個(gè)headerView,相互之間互不干擾,代碼簡(jiǎn)潔,維護(hù)成本低。

其他介紹 01.關(guān)于博客匯總鏈接

1.技術(shù)博客匯總

2.開(kāi)源項(xiàng)目匯總

3.生活博客匯總

4.喜馬拉雅音頻匯總

5.其他匯總

02.關(guān)于我的博客

我的個(gè)人站點(diǎn):www.yczbj.org,www.ycbjie.cn

github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/...

簡(jiǎn)書(shū):http://www.jianshu.com/u/b7b2...

csdn:http://my.csdn.net/m0_37700275

喜馬拉雅聽(tīng)書(shū):http://www.ximalaya.com/zhubo...

開(kāi)源中國(guó):https://my.oschina.net/zbj161...

泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...

郵箱:[email protected]

阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV

segmentfault頭條:https://segmentfault.com/u/xi...

掘金:https://juejin.im/user/593943...

項(xiàng)目案例地址:https://github.com/yangchong2...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74797.html

相關(guān)文章

  • 復(fù)雜type頁(yè)面封裝庫(kù),支持種狀態(tài)切換和下拉刷新上拉加載

    摘要:支持復(fù)雜頁(yè)面,例如添加自定義頭部和底部布局,支持橫向滑動(dòng),還可以支持粘貼頭部類(lèi)似微信好友分組,支持不規(guī)則瀑布流效果,支持側(cè)滑刪除功能。十分方便實(shí)現(xiàn)復(fù)雜的布局頁(yè)面,結(jié)構(gòu)上層次分明,便于維護(hù)。 目錄介紹 1.復(fù)雜頁(yè)面庫(kù)介紹 2.本庫(kù)優(yōu)勢(shì)亮點(diǎn) 2.1 支持多種狀態(tài)切換管理 2.2 支持添加多個(gè)header和footer 2.3 支持側(cè)滑功能和拖拽移動(dòng) 2.4 其他亮點(diǎn)介紹 3.如...

    Karrdy 評(píng)論0 收藏0
  • RecyclerView問(wèn)題匯總

    摘要:缺點(diǎn)自動(dòng)裝箱的存在意味著每一次插入都會(huì)有額外的對(duì)象創(chuàng)建。對(duì)象本身是一層額外需要被創(chuàng)建以及被垃圾回收的對(duì)象。相較于我們舍棄了和類(lèi)型的放棄了并依賴(lài)于二分法查找。 目錄介紹 25.0.0.0 請(qǐng)說(shuō)一下RecyclerView?adapter的作用是什么,幾個(gè)方法是做什么用的?如何理解adapter訂閱者模式? 25.0.0.1 ViewHolder的作用是什么?如何理解ViewHolder...

    boredream 評(píng)論0 收藏0
  • RecyclerView封裝庫(kù)和綜合案例【包含25篇博客】

    摘要:支持復(fù)雜頁(yè)面,例如添加自定義頭部和底部布局,支持橫向滑動(dòng),還可以支持粘貼頭部類(lèi)似微信好友分組,支持不規(guī)則瀑布流效果,支持側(cè)滑刪除功能。支持粘貼頭部的需求效果,這種效果類(lèi)似微信好友分組的那種功能界面。 目錄介紹 1.復(fù)雜頁(yè)面庫(kù)介紹 2.本庫(kù)優(yōu)勢(shì)亮點(diǎn) 2.1 支持多種狀態(tài)切換管理 2.2 支持添加多個(gè)header和footer 2.3 支持側(cè)滑功能和拖拽移動(dòng) 2.4 其他亮點(diǎn)介紹 ...

    silenceboy 評(píng)論0 收藏0
  • RecyclerView瀑布流優(yōu)化方案探討

    摘要:是規(guī)則的瀑布流。普通的尺寸會(huì)出現(xiàn)錯(cuò)位的問(wèn)題索引這個(gè)是右邊這個(gè)是左邊間距解決辦法,可以通過(guò)里的來(lái)判斷,這個(gè)方法不管你高度怎樣,他都是左右左右開(kāi)始排列的。 目錄介紹 01.規(guī)則瀑布流實(shí)現(xiàn)02.不規(guī)則瀑布流實(shí)現(xiàn)2.1 實(shí)現(xiàn)方式2.2 遇到問(wèn)題03.瀑布流上拉加載04.給瀑布流設(shè)置分割線05.自定義Manager崩潰06.如何避免刷新抖動(dòng)07.為何有時(shí)出現(xiàn)跳動(dòng)08.瀑布流圖片優(yōu)化09.onBi...

    zhaofeihao 評(píng)論0 收藏0
  • RecyclerView用法和源碼深度解析

    摘要:此方法應(yīng)由實(shí)現(xiàn)使用,以獲取視圖來(lái)表示來(lái)自的數(shù)據(jù)。如果適配器沒(méi)有指示給定位置上的數(shù)據(jù)已更改,則回收程序?qū)L試發(fā)回一個(gè)以前為該數(shù)據(jù)初始化的報(bào)廢視圖,而不進(jìn)行重新綁定。如果它只附加了一個(gè)適配器,并且新適配器使用與不同的,則將清除其緩存。 目錄介紹 1.RecycleView的結(jié)構(gòu) 2.Adapter 2.1 RecyclerView.Adapter扮演的角色 2.2 重寫(xiě)的方法 2.3...

    ShowerSun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<