1. 程式人生 > >偷懶新姿勢,打造屬於RecyclerView的萬能介面卡Adapter和ViewHolder

偷懶新姿勢,打造屬於RecyclerView的萬能介面卡Adapter和ViewHolder

前言

昨天開始接觸江湖口碑很好的RecyclerView,事實上,我已經被她的強大所征服了!資源回收,資料繫結,佈局顯示,分割線,Item動畫多個模組高度解耦,靈活優雅。其實,RecyclerView在使用上已經是相當簡單了(個人覺得),但仍有很多程式碼是可以加以封裝的。今天受簡書上一篇博文的啟發,作為寫程式碼喜歡優(tou)雅(lan)的人,想到了一種封裝方式,打造萬能介面卡,供大家食用。

正統模式:

public class SimplerItemAdapter extends RecyclerView.Adapter<SimplerItemAdapter.SimpleItemViewHolder
> {
private List <String> items; public SimplerItemAdapter (@NonNull List<String> dateItems ) { this.items = (dateItems != null ? dateItems : new ArrayList<String>()); } @Override public SimpleItemViewHolder onCreateViewHolder (ViewGroup viewGroup, int viewType) { View itemView = LayoutInflater.from( viewGroup.getContext ()).inflate(R.layout .item, viewGroup, false
); return new SimpleItemViewHolder(itemView); } @Override public void onBindViewHolder (SimpleItemViewHolder viewHolder, int position) { viewHolder.textView .setText(items.get (position)); } @Override public int getItemCount () { return (this.items != null) ? this .items. size() : 0
; } protected final static class SimpleItemViewHolder extends RecyclerView.ViewHolder { protected TextView textView ; public SimpleItemViewHolder (View itemView) { super(itemView); this.textView = (TextView) itemView.findViewById (R. id.text); } } }
  • 首先,
    @Override public int getItemCount () {
    return (this.items != null) ? this .items. size() : 0 ;
    }
    這段程式碼完全可以封裝起來的。
  • onCreatedViewHolder()方法作用是繫結item檢視,可以進一步封裝,給子類提供一個getLayoutItemId的抽象方法,這樣就可以簡化成一行程式碼了。
  • 因此我們發現,這個adapter的核心程式碼在與onBindViewHolder()中,作用是將資料跟檢視(ViewHolder)繫結,可以給子類提供一個bindData()抽象方法。
  • 當然了,使用泛型也是極好的,拓廣了adapter的使用範圍。
  • 新增點選事件的監聽也可以封裝到萬能adapter中,子類就不用再寫item點選事件處理程式碼了

封裝後的Adapter

public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerViewHolder> {
    protected final List<T> mData;
    protected final Context mContext;
    protected LayoutInflater mInflater;
    private OnItemClickListener mClickListener;
    private OnItemLongClickListener mLongClickListener;

    public BaseRecyclerAdapter(Context ctx, List<T> list) {
        mData = (list != null) ? list : new ArrayList<T>();
        mContext = ctx;
        mInflater = LayoutInflater.from(ctx);
    }

    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final RecyclerViewHolder holder = new RecyclerViewHolder(mContext,
                mInflater.inflate(getItemLayoutId(viewType), parent, false));
        if (mClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mClickListener.onItemClick(holder.itemView, holder.getLayoutPosition());
                }
            });
        }
        if (mLongClickListener != null) {
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    mLongClickListener.onItemLongClick(holder.itemView, holder.getLayoutPosition());
                    return true;
                }
            });
        }
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerViewHolder holder, int position) {
        bindData(holder, position, mData.get(position));
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }

    public void add(int pos, T item) {
        mData.add(pos, item);
        notifyItemInserted(pos);
    }

    public void delete(int pos) {
        mData.remove(pos);
        notifyItemRemoved(pos);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mClickListener = listener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener listener) {
        mLongClickListener = listener;
    }

    abstract public int getItemLayoutId(int viewType);

    abstract public void bindData(RecyclerViewHolder holder, int position, T item);

    public interface OnItemClickListener {
        public void onItemClick(View itemView, int pos);
    }

    public interface OnItemLongClickListener {
        public void onItemLongClick(View itemView, int pos);
    }
}

Super ViewHolder!

其實,這還沒完呢!重頭戲在ViewHolder上!RecyclerView強制我們使用ViewHolder模式,然而缺不可避免地要寫findViewById程式碼,有沒有辦法不寫這樣的程式碼呢?甚至連ViewHolder都不寫呢?當然可以!

public class RecyclerViewHolder extends RecyclerView.ViewHolder {
    private SparseArray<View> mViews;//集合類,layout裡包含的View,以view的id作為key,value是view物件
    private Context mContext;//上下文物件

    public RecyclerViewHolder(Context ctx, View itemView) {
        super(itemView);
        mContext = ctx;
        mViews = new SparseArray<View>();
    }

    private <T extends View> T findViewById(int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    public View getView(int viewId) {
        return findViewById(viewId);
    }

    public TextView getTextView(int viewId) {
        return (TextView) getView(viewId);
    }

    public Button getButton(int viewId) {
        return (Button) getView(viewId);
    }

    public ImageView getImageView(int viewId) {
        return (ImageView) getView(viewId);
    }

    public ImageButton getImageButton(int viewId) {
        return (ImageButton) getView(viewId);
    }

    public EditText getEditText(int viewId) {
        return (EditText) getView(viewId);
    }

    public RecyclerViewHolder setText(int viewId, String value) {
        TextView view = findViewById(viewId);
        view.setText(value);
        return this;
    }

    public RecyclerViewHolder setBackground(int viewId, int resId) {
        View view = findViewById(viewId);
        view.setBackgroundResource(resId);
        return this;
    }

    public RecyclerViewHolder setClickListener(int viewId, View.OnClickListener listener) {
        View view = findViewById(viewId);
        view.setOnClickListener(listener);
        return this;
    }
}

該類的核心方法是private T findViewById(int viewId),核心成員變數是private SparseArray mViews; 不信可以不寫一句ViewHolder程式碼?接下來看看用法。

實踐用法

新增Adapter僅需短短的幾行程式碼:

Adapter = new BaseRecyclerAdapter<String>(this,mDataList) {
            @Override
            public int getItemLayoutId(int viewType) {
                return R.layout.item;
            }
            @Override
            public void bindData(RecyclerViewHolder holder, int position,String item) {
                //呼叫holder.getView(),getXXX()方法根據id得到控制元件例項,進行資料繫結即可
                holder.setText(R.id.tv_num,item)
                        .getTextView(R.id.tv_title,item).setText(item);
            }
        };

完整程式碼:

    private void init() {
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        mDataList = new ArrayList<>();
        for (int i = 0; i <= 100; i++) {
            mDataList.add(String.valueOf(i));
        }
        //設定item動畫
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdapter = new BaseRecyclerAdapter<String>(this,mDataList) {
            @Override
            public int getItemLayoutId(int viewType) {
                return R.layout.item;
            }
            @Override
            public void bindData(RecyclerViewHolder holder, int position,String item) {
                //呼叫holder.getView(),getXXX()方法根據id得到控制元件例項,進行資料繫結即可
                holder.setText(R.id.tv_num,item)
                        .getTextView(R.id.tv_title,item).setText(item);
            }
        };
        recyclerView.setAdapter(mAdapter);
        //新增item點選事件監聽
        ((BaseRecyclerAdapter)mAdapter).setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View itemView, int pos) {
                Toast.makeText(AdapterTestActivity.this, "click " + pos, Toast.LENGTH_SHORT).show();
            }
        });
        ((BaseRecyclerAdapter)mAdapter).setOnItemLongClickListener(new BaseRecyclerAdapter.OnItemLongClickListener() {
            @Override
            public void onItemLongClick(View itemView, int pos) {
                Toast.makeText(AdapterTestActivity.this, "long click " + pos, Toast.LENGTH_SHORT).show();
            }
        });
        //設定佈局樣式LayoutManager
        recyclerView.setLayoutManager(new LinearLayoutManager(AdapterTestActivity.this, LinearLayoutManager.VERTICAL, false));
//        recyclerView.addItemDecoration(new ItemDividerDecoration(MainActivity.this, OrientationHelper.VERTICAL));

    }

如果覺得有什麼不妥之處或建議,敬請指教!
完整專案程式碼已上傳至Github。—Github跳轉

相關推薦

偷懶姿勢打造屬於RecyclerView萬能介面卡AdapterViewHolder

前言 昨天開始接觸江湖口碑很好的RecyclerView,事實上,我已經被她的強大所征服了!資源回收,資料繫結,佈局顯示,分割線,Item動畫多個模組高度解耦,靈活優雅。其實,RecyclerView在使用上已經是相當簡單了(個人覺得),但仍有很多程式碼是可以

屬於RecyclerView萬能介面卡AdapterViewHolder

前言 昨天開始接觸江湖口碑很好的RecyclerView,事實上,我已經被她的強大所征服了!資源回收,資料繫結,佈局顯示,分割線,Item動畫多個模組高度解耦,靈活優雅。其實,RecyclerView在使用上已經是相當簡單了(個人覺得),但仍有很多程式碼是可以加以封裝的。今天受簡書上一篇博文的啟發,作為寫

(再次更新)打造RecyclerView萬能介面卡上拉重新整理下拉載入

入行幾個月了,一直想自己封裝一些類,剛好遇到了這個問題,現在跟大家分享。 注意點 1 泛型擦除 2 需要防止型別轉換異常 github地址:https://github.com/zw21544182/MyBaseDemo (裡面還有部分FileUtil

【算法學習】老算法姿勢STL——Heap

內存 str 關系 priority bug 普通 數組 關於 cto “堆”是一個大家很熟悉的數據結構,它可以在\(O(log\;n)\)的時間內維護集合的極值。 這都是老套路了,具體的內部實現我也就不談了。 我一般來說,都是用queue庫中的priority_queue

張書樂:瞬時播放熱劇成盜版姿勢網絡直播此刻已無技可炫?

直播以後在直播間裏的才藝展示,或許觀眾點歌、主播唱歌將會引發各種侵權;或許你在一場賽事旁直播是侵權,在直播的時候,背後的電視機上“無意”出現了電視劇畫面,還是侵權……綜合媒體報道,8月,愛奇藝狀告多玩公司及旗下直播平臺YY侵害了愛奇藝公司著作權的案件,經海澱區法院最終認定,YY平臺的多玩公司侵害了愛奇藝公司著

薅資本主義羊毛姿勢英偉達GPU免費用

作者 | 阿司匹林 出品 | 人工智慧頭條(公眾號ID:AI_Thinker) 在到處都是開源工具和學習資料的今天,深度學習的門檻已經大大降低。然而,學習的門檻降低並不意味著學習的成本降低了,比如說動則上萬的 GPU。 不管是買 GPU,還是買雲服務,

自定義瀏覽器滾動條的樣式打造屬於你的滾動條風格

前段時間,到網上找素材時,看到了一個很個性的滾動條式,開啟Chrome的除錯工具看了一下,發現不是用JavaScript來模擬實現的,覺得有必要折騰一下。於是在各大瀏覽器中對比了一下,發現只用Chrome適用,也就是說這個用的是Chrome的私有CSS屬性。便百之谷之後,發現原來不僅僅只用Chrome,其它的

自定義瀏覽器滾動條的樣式打造屬於你的滾動條風格——相容IEwebkit(ff不支援)

前段時間,到網上找素材時,看到了一個很個性的滾動條式,開啟Chrome的除錯工具看了一下,發現不是用JavaScript來模擬實現的,覺得 有必要折騰一下。於是在各大瀏覽器中對比了一下,發現只用Chrome適用,也就是說這個用的是Chrome的私有CSS屬性。便百之谷之後,發現原來不 僅僅只用Chrome,

Android(無需javabean)的RecyclerView萬能介面卡解耦從這裡做起

先介紹下為什麼這麼做,因為RecyclerView需要一個javabean,同時呢,對於整個系統中的一個物件,也需要建造一個javabean。但是很明顯,RecyclerView中的那個bean顯然是整個系統中那個物件javabean的子集。所以我覺得不應該專門為Recyc

置換輪換(姿勢摘自黑書)

參考論文 這一部分在黑書中, 是在群論這一部分介紹的 所以我們先了解什麼是群 群的定義 給定一個集合G={a,b,c…}和集合G上的一個二元計算*,滿足以下四個條件: (1)封閉性 若a,b∈G,則存在唯一確定的c∈G,使得a*b=c;

肝了兩天IntelliJ IDEA 2020解鎖11種姿勢 真香!!!

> IDEA2020版本正式釋出已經有3個月了,當時由於各方面原因(太懶)也沒有去嘗試新功能。於是這個週末特意去在另一個電腦上下載了最新版的IDEA,並嘗試了一下。總的來說呢,體驗上明顯的提升。 作為一個大版本的升級,自然也增加了許多新功能。個人體驗了兩天, - 支援Java14,並且可以直接通過I

RecyclerView 萬能介面卡的抽取

//這裡我們寫的複雜的RecyclerView對條目的抽取,我們只設置了三個型別,頭佈局(輪播圖),身體佈局,腳佈局(上拉重新整理)的複雜條目的抽取框架 import android.support.v7.widget.RecyclerView; import androi

媒體內容創作的3個超實用萬能開頭金句!打造屬於你的10萬+創意素材 | 黎想

大家好!我是藝形藝意工作室創始人,騰訊網、百度網、今日頭條、搜狐網等網站知名專欄作者,《新媒體推廣運營實戰大全》作者黎想,百度單篇推文10萬+。曾結合親身經理給大家分享一位優秀的新媒體運營人員如何通過"四步引爆法"策劃出引爆眾人蔘與的推廣活動等文章,引發了眾多新媒體從業者的共鳴。

RecyclerView打造萬能介面卡點選事件5.0水波紋點選效果

一.前言 最近使用到RecyclerView,RecyclerView使用詳解戳這裡,由於使用過張鴻洋大神的ListView萬能Adapter,感覺RecyclerView的Adapter編寫還是太麻煩了,而且沒有點選事件,ok,參考ListView的萬能Ad

張書樂:把遊戲展辦成場廟會這是個姿勢

遊戲展“遊戲雜誌,因為攻略秘技和新遊推薦都上網了,結果一家家關張了;遊戲展會,與蘋果一樣,黑科技早就曝光了,且Showgirl裹得越來越嚴實,結果已經沒有多少人關註了。”一個遊戲圈的老友前些天在飯桌上和我這樣盤點近年來遊戲外圍行業的變化。以展會為例,盡管7月末結束的2017年Chinajoy,4天累計入場人數

酷斃了!python用37行代碼打造屬於自己的音樂播放器附源碼

python 爬蟲 音樂 代碼想不想手動打造一款專屬於你的播放器,同時練練Python編程? 如果想,那就立即行動吧! 所需庫pygametkintermutagen 至於它們的使用,可以瀏覽一下文檔,如果你想做更功能強大的播放器,那必須好好看看哦! 設計思路作為版本0,我們並不想做太復雜的項目。只需實現以下

創夢天地關嵩:借力騰訊雲打造文娛生態——雲+未來峰會回顧

發布 幫助 devel 質量 戰略合作 明顯 unity 入口 可能 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 今年騰訊雲+未來峰會主題的關鍵詞是“煥·啟”,這是包含無限希望的兩個字,讓人倍感振奮。“煥·啟”是什麽意思?在我的理解中,“煥·啟”本身就是激

用爬蟲Flask打造屬於自己的電影網站完整教程送上!

alt mysql服務器 學習 安裝 友好 點擊 沒有 網易 sql安裝 也許你曾經為了一部電影找遍全網卻沒發現任何有用的資源,也許你曾經被披著電影外衣的網站忽悠進去而染上×××病毒。一部小小的電影搞得你心力交瘁,懷疑人生。不過,作為一名合格的程序員,一向以write th

BIOTA與英國倫敦大學學院聯合打造一代公有鏈

倫敦2018年11月9日電 /美通社/ -- 倫敦時間11月2日,BIOTA 與英國倫敦大學學院(UCL)達成戰略合作,與倫敦大學學院區塊鏈科技研發中心(CBT)簽署了合作合約,將在接下來的時間裡與 BIOTA 攜手,打造一個更適用於商業的區塊鏈底層技術。

粵出"飛龍"打造制造廣東樣本

今天 飛龍工業網際網路平臺在廣東正式釋出啦 不僅能夠輻射粵港澳大灣區 還將幫助廣東打造新能源、電氣裝備等 八大工業網際網路產業叢集 作為中國的製造大省之一 廣東的產業規模位列全球第五 而近10年 轉型升級已然成為了廣東製造業發展的關鍵詞 雲端計算、大資料、人工智慧 則成為當地製造發展新