必須是最另類、最輕量級的、最容易看懂、給你無限意贏空間的 RecyclerView 的通用Adapter
專案: Adapter-master" target="_blank" rel="nofollow,noindex">RVAdapter-master
前言:各位是否有過自己封裝通用Adapter,是否使用過第三方的框架,是不是感覺使用別人的框架有很多限制,過度封裝讓你使用的不爽,解鎖的姿勢不多,那強烈建議你看完本文章,並clone專案,執行一下,再看看 原始碼(原始碼超級簡單,關鍵就三個類,包你看懂,還有收穫,看不懂找我) , 我的偽封裝可以重新整理你對RecyclerView Adapter 的認識 ,並可以給你無限的意贏空間, 解鎖你能想到的任意姿勢 。
先給大家鋪墊一下,偽框架的由來: 剛到新公司,發現新同事對RecyclerView不是特別熟悉,以至於他在自定義Adapter的時候寫了一段錯誤,但卻特別有意思的程式碼,讓我重新對RecyclerView的Adapter有了新的認識,也正因為他的有意思的程式碼才有了今天我這個 RecyclerView的通用Adapter偽封裝 ,說句體外話,現在這個偽框架已經在公司用起來了,別提多爽。 具體請往下看。
以前我們正常的使用Adapter
這裡只列出部分關鍵程式碼
解釋: 正常來說我們定義多樣式RecyclerView的Adapter時,我們會先定義一些 itemtype ,然後通過判斷不同的type,建立相應的ViewHolder及view,在onBindViewHolder()處理相應的邏輯。
//重寫getItemViewType方法 根據條件返回條目的型別 @Override public int getItemViewType(int position) { MoreTypeBean moreTypeBean = mData.get(position); if (moreTypeBean.type == 0) { return TYPE_PULL_IMAGE; } else if (moreTypeBean.type == 1) { return TYPE_RIGHT_IMAGE; } else { return TYPE_THREE_IMAGE; } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //建立不同的 ViewHolder View view; //根據viewtype來判斷 if (viewType == TYPE_PULL_IMAGE) { view =View.inflate(parent.getContext(),R.layout.item_pull_img,null); return new PullImageHolder(view); } else if (viewType == TYPE_RIGHT_IMAGE) { view =View.inflate(parent.getContext(),R.layout.item_right_img,null); return new RightImageHolder(view); } else { view =View.inflate(parent.getContext(),R.layout.item_three_img,null); return new ThreeImageHolder(view); } }
他寫的(這裡我只羅列一些虛擬碼,表達他的大概意思)
//重寫getItemViewType方法 根據條件返回條目的型別 @Override public int getItemViewType(int position) { //這裡是關鍵點所在 if (position == 0) { return R.layout.layout_a; } else if (position == 1) { return R.layout.layout_b; } else { return R.layout.layout_c; } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new GViewHolder(View.inflate(parent.getContext(),viewType)) } @Override public void onBindViewHolder(GViewHolder holder, int position) { if (holder.item == R.layout.layout_a) { //todo layout_a處理邏輯 } else if (item == R.layout.layout_b) { //todo 處理layout_b 邏輯 } else if (item == R.layout.layout_c) { //todo 處理layout_c 邏輯 } }
當時看到他這段程式碼心裡想法的變化:
第一眼,果然對RecyclerView 不熟,基本的使用都寫的有問題
->
再仔細一想,結果是對的啊,而且不用再定義type常量,不用再定義過多的viewHolder
->
再多看幾眼,我被他這種另類的寫法征服了。
->
於是我重新寫了RecyclerView的通用Adapter封裝,也就有了今天的 RecyclerView的通用Adapter偽封裝,卻給你無比巨大的意贏空間
感悟(這段文字有點多,慢慢看,體會,很有意思):仔細對比正常寫法和他寫的,你會發現根據Google官方對方法的定義,確實他寫的是一段錯誤程式碼,但是仔細看他的程式碼你會發現很有意思,為什麼呢?在 getItemViewType() 將佈局資源ID,直接返回,在 onBindViewHolder(GViewHolder holder, int position) 方法直接從holder中將佈局的資源ID拿出來做判斷,做相應的邏輯,看下來少了很多程式碼,邏輯比以前的寫法更加清晰了,簡潔。
我敢肯定看到這裡,你可能心裡還是懵的,不就是將LayoutId作為ItemType直接返回了嗎,那麼請你到我的原始碼中看看,我保證你看的懂,而且會感覺發現新大陸
RVAdapter-master我的偽封裝關鍵只有三個類所以程式碼我就不講了,大家進原始碼看看
我這個偽框架的使用
單樣式使用:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view); rvContent = findViewById(R.id.rv_content); RVSimpleAdapter adapter = new RVSimpleAdapter<String>(this, getDatas(), R.layout.item_simple) { @Override public void convert(ViewHolder holder, String item) { holder.setText(R.id.tv_name, item); } }; //垂直 adapter.attachLinearRv(rvContent, RVSimpleAdapter.VERTICAL); //水平 //adapter.attachLinearRv(rvContent, RVSimpleAdapter.HORIZONTAL); //自定義 //rvContent.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)); //rvContent.setItemAnimator(new DefaultItemAnimator()); //rvContent.setAdapter(adapter); }

單樣式.png
多樣式使用
繼承實現
class MultiAdater extends RvBaseAdapter<Integer> { MultiAdater(Context context, List<Integer> datas) { super(context, datas); } @Override public int getLayoutId(int position, Integer item) { return item % 2 == 0 ? R.layout.item_simple : R.layout.item_red_background; } @Override public void convert(ViewHolder holder, Integer item, int layoutId, int position) { switch (layoutId) { case R.layout.item_simple: holder.setText(R.id.tv_name, String.format("樣式一item:%s", item)); break; case R.layout.item_red_background: holder.setText(R.id.tv_content, String.format("樣式二item:%s", item)); break; default: break; } } }
簡單使用
new MultiAdater(this, getDatas()).attachLinearRv(recyclerView, RVSimpleAdapter.VERTICAL);

多樣式.png
佈局多樣式,並且資料來源是多種物件
class ExtraAdater extends RvBaseAdapter<Object> { ExtraAdater(Context context, List<Object> datas) { super(context, datas); } @Override public int getLayoutId(int position, Object item) { if (item instanceof A) { return R.layout.item_simple; } else { return R.layout.item_red_background; } } @Override public void convert(ViewHolder holder, Object item, int layoutId, int position) { if (item instanceof A) { holder.setText(R.id.tv_name, String.format("物件: %s", ((A) item).name)); } else { holder.setText(R.id.tv_content, String.format("物件: %s", ((B) item).name)); } } }

多種物件多樣式.png