摘要:,無法復(fù)用,假如有多個頁面有多個,那么就要寫多個。綁定,主要作用是綁定數(shù)據(jù)到正確的視圖上。可維護性不同的列表類型由添加處理,哪怕添加多個,相互之間互不干擾,代碼簡潔,維護成本低。
目錄介紹
01.先看看實際需求
02.adapter實現(xiàn)多個type
03.這樣寫的弊端
04.如何優(yōu)雅實現(xiàn)adapter封裝
好消息博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識點,Android技術(shù)博客,Python學(xué)習(xí)筆記等等,還包括平時開發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續(xù)完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計N篇[近100萬字,陸續(xù)搬到網(wǎng)上],轉(zhuǎn)載請注明出處,謝謝!
鏈接地址:https://github.com/yangchong2...
如果覺得好,可以star一下,謝謝!當(dāng)然也歡迎提出建議,萬事起于忽微,量變引起質(zhì)變!
01.先看看實際需求比如一個APP的首頁,包含Banner區(qū)、廣告區(qū)、文本內(nèi)容、圖片內(nèi)容、新聞內(nèi)容等等。
RecyclerView 可以用ViewType來區(qū)分不同的item,也可以滿足需求,但還是存在一些問題,比如:
1,在item過多邏輯復(fù)雜列表界面,Adapter里面的代碼量龐大,邏輯復(fù)雜,后期難以維護。
2,每次增加一個列表都需要增加一個Adapter,重復(fù)搬磚,效率低下。
3,無法復(fù)用adapter,假如有多個頁面有多個type,那么就要寫多個adapter。
4,要是有局部刷新,那么就比較麻煩了,比如廣告區(qū)也是一個九宮格的RecyclerView,點擊局部刷新當(dāng)前數(shù)據(jù),比較麻煩。
02.adapter實現(xiàn)多個type
通常寫一個多Item列表的方法
根據(jù)不同的ViewType 處理不同的item,如果邏輯復(fù)雜,這個類的代碼量是很龐大的。如果版本迭代添加新的需求,修改代碼很麻煩,后期維護困難。
主要操作步驟
在onCreateViewHolder中根據(jù)viewType參數(shù),也就是getItemViewType的返回值來判斷需要創(chuàng)建的ViewHolder類型
在onBindViewHolder方法中對ViewHolder的具體類型進行判斷,分別為不同類型的ViewHolder進行綁定數(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 List03.這樣寫的弊端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在開頭 }else { return mData.get(position).type;//type 的值為TYPE_AD,TYPE_IMAGE,TYPE_AD,等其中一個 } } @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); //綁定控件 } } }
上面那樣寫的弊端
類型檢查與類型轉(zhuǎn)型,由于在onCreateViewHolder根據(jù)不同類型創(chuàng)建了不同的ViewHolder,所以在onBindViewHolder需要針對不同類型的ViewHolder進行數(shù)據(jù)綁定與邏輯處理,這導(dǎo)致需要通過instanceof對ViewHolder進行類型檢查與類型轉(zhuǎn)型。
不利于擴展,目前的需求是列表中存在5種布局類類型,那么如果需求變動,極端一點的情況就是數(shù)據(jù)源是從服務(wù)器獲取的,數(shù)據(jù)中的model決定列表中的布局類型。這種情況下,每當(dāng)model改變或model類型增加,我們都要去改變adapter中很多的代碼,同時Adapter還必須知道特定的model在列表中的位置(position)除非跟服務(wù)端約定好,model(位置)不變,很顯然,這是不現(xiàn)實的。
不利于維護,這點應(yīng)該是上一點的延伸,隨著列表中布局類型的增加與變更,getItemViewType、onCreateViewHolder、onBindViewHolder中的代碼都需要變更或增加,Adapter 中的代碼會變得臃腫與混亂,增加了代碼的維護成本。
04.如何優(yōu)雅實現(xiàn)adapter封裝
核心目的就是三個
避免類的類型檢查與類型轉(zhuǎn)型
增強Adapter的擴展性
增強Adapter的可維護性
當(dāng)列表中類型增加或減少時Adapter中主要改動的就是getItemViewType、onCreateViewHolder、onBindViewHolder這三個方法,因此,我們就從這三個方法中開始著手。
既然可能存在多個type類型的view,那么能不能把這些比如banner,廣告,文本,視頻,新聞等當(dāng)做一個HeaderView來操作。
在getItemViewType方法中。
減少if之類的邏輯判斷簡化代碼,可以簡單粗暴的用hashCode作為增加type標(biāo)識。
通過創(chuàng)建列表的布局類型,同時返回的不再是簡單的布局類型標(biāo)識,而是布局的hashCode值
private ArrayListheaders = 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); } /** * 獲取類型,主要作用是用來獲取當(dāng)前項Item(position參數(shù))是哪種類型的布局 * @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類型 * @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類型的view,則通過onBindView進行數(shù)據(jù)綁定。
/** * 綁定viewHolder,主要作用是綁定數(shù)據(jù)到正確的Item視圖上。當(dāng)視圖從不可見到可見的時候,會調(diào)用這個方法。 * @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()); } ```
如何使用,如下所示,這個就是banner類型,可以說是解耦了之前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)心不同的列表類型在列表中的位置,因此對于Adapter來說列表類型可以隨意增加或減少。十分方便,同時設(shè)置類型view的布局和數(shù)據(jù)綁定都不需要在adapter中處理。充分解耦。
可維護性——不同的列表類型由adapter添加headerView處理,哪怕添加多個headerView,相互之間互不干擾,代碼簡潔,維護成本低。
其他介紹 01.關(guān)于博客匯總鏈接1.技術(shù)博客匯總
2.開源項目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關(guān)于我的博客我的個人站點:www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡書:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽書:http://www.ximalaya.com/zhubo...
開源中國:https://my.oschina.net/zbj161...
泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...
郵箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault頭條:https://segmentfault.com/u/xi...
掘金:https://juejin.im/user/593943...
項目案例地址:https://github.com/yangchong2...文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/74797.html
摘要:支持復(fù)雜頁面,例如添加自定義頭部和底部布局,支持橫向滑動,還可以支持粘貼頭部類似微信好友分組,支持不規(guī)則瀑布流效果,支持側(cè)滑刪除功能。十分方便實現(xiàn)復(fù)雜的布局頁面,結(jié)構(gòu)上層次分明,便于維護。 目錄介紹 1.復(fù)雜頁面庫介紹 2.本庫優(yōu)勢亮點 2.1 支持多種狀態(tài)切換管理 2.2 支持添加多個header和footer 2.3 支持側(cè)滑功能和拖拽移動 2.4 其他亮點介紹 3.如...
摘要:缺點自動裝箱的存在意味著每一次插入都會有額外的對象創(chuàng)建。對象本身是一層額外需要被創(chuàng)建以及被垃圾回收的對象。相較于我們舍棄了和類型的放棄了并依賴于二分法查找。 目錄介紹 25.0.0.0 請說一下RecyclerView?adapter的作用是什么,幾個方法是做什么用的?如何理解adapter訂閱者模式? 25.0.0.1 ViewHolder的作用是什么?如何理解ViewHolder...
摘要:支持復(fù)雜頁面,例如添加自定義頭部和底部布局,支持橫向滑動,還可以支持粘貼頭部類似微信好友分組,支持不規(guī)則瀑布流效果,支持側(cè)滑刪除功能。支持粘貼頭部的需求效果,這種效果類似微信好友分組的那種功能界面。 目錄介紹 1.復(fù)雜頁面庫介紹 2.本庫優(yōu)勢亮點 2.1 支持多種狀態(tài)切換管理 2.2 支持添加多個header和footer 2.3 支持側(cè)滑功能和拖拽移動 2.4 其他亮點介紹 ...
摘要:是規(guī)則的瀑布流。普通的尺寸會出現(xiàn)錯位的問題索引這個是右邊這個是左邊間距解決辦法,可以通過里的來判斷,這個方法不管你高度怎樣,他都是左右左右開始排列的。 目錄介紹 01.規(guī)則瀑布流實現(xiàn)02.不規(guī)則瀑布流實現(xiàn)2.1 實現(xiàn)方式2.2 遇到問題03.瀑布流上拉加載04.給瀑布流設(shè)置分割線05.自定義Manager崩潰06.如何避免刷新抖動07.為何有時出現(xiàn)跳動08.瀑布流圖片優(yōu)化09.onBi...
摘要:此方法應(yīng)由實現(xiàn)使用,以獲取視圖來表示來自的數(shù)據(jù)。如果適配器沒有指示給定位置上的數(shù)據(jù)已更改,則回收程序?qū)L試發(fā)回一個以前為該數(shù)據(jù)初始化的報廢視圖,而不進行重新綁定。如果它只附加了一個適配器,并且新適配器使用與不同的,則將清除其緩存。 目錄介紹 1.RecycleView的結(jié)構(gòu) 2.Adapter 2.1 RecyclerView.Adapter扮演的角色 2.2 重寫的方法 2.3...
閱讀 2285·2021-11-15 11:37
閱讀 2954·2021-09-01 10:41
閱讀 787·2019-12-27 11:58
閱讀 747·2019-08-30 15:54
閱讀 715·2019-08-30 13:52
閱讀 2930·2019-08-29 12:22
閱讀 1075·2019-08-28 18:27
閱讀 1452·2019-08-26 18:42