1. 程式人生 > >福利:打造一個萬能的RecyclerViewAdapter

福利:打造一個萬能的RecyclerViewAdapter

由於本鳥在之前確實沒有用到過RecyclerView,正好今天比較閒,所以乾脆找點資料,學習了一下這個神奇的控制元件。

特點:RecyclerView可以實現線性佈局(橫向線性佈局和縱向線性佈局),網格佈局(有了這個,基本上可以拋棄GridView了),還可以實現瀑布流,就是那種很炫的效果,這種佈局目前來說還是比較流行的。

使用起來跟ListView差不多吧,無非就是在資原始檔中定義這個控制元件,給它一個id,然後到程式碼裡通過findViewById()找到它,然後設定一系列引數,最後通過setAdapter給它一組資料,顯示到介面上就ok了,這篇文章主要研究Adapter,其他的暫且擱在一邊。

我們需要繼承RecyclerView.Adapter這個類,來實現我們自己的Adapter,看程式碼

public class NormalAdapter extends RecyclerView.Adapter {
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //這裡返回一個Holder,在ListView中我們也會使用ViewHolder來減少findViewById()的次數,提高listview效率
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        //這裡主要進行一些View的,比如給按鈕設定個點選監聽器,或者給TextView設定文字,或者給ImageView設定src,懂了吧,反正就是初始化

    }
    
    @Override
    public int getItemCount() {
        //返回資料集的長度
        return 0;
    }
}

 剛開始如果我們什麼都不做,那程式碼就是這樣的,必須要override三個方法,看上面的程式碼就知道了,ViewHolder暫時 先別管,不懂得同學,你就理解成ListView中的Holder好了,都是一樣的。

好了,廢話不多說,我問一個問題,你們仔細看,這個NormalAdapter的程式碼量多不多?(請思考5分鐘)

........................

好了,思考時間結束。覺得程式碼量不多的人,可以把電腦關掉,洗洗睡了。。。覺得程式碼量多的人,可以自行往下閱讀,我教你如何打造一款萬能的Adapter,只要寫一個Adapter,就可以“到處”執行微笑微笑微笑

設想一下,一個專案中,我們如果要寫幾十個Adapter,每個Adapter都要這麼重複來重複去的,事件浪費掉了不去說,家裡老婆孩子還等著你回家做飯吃呢,而且,如果程式碼出問題了,你還要一個個Adapter去看,到底是哪個Adapter出問題了,能把你搞死,我反正要被搞死了。。。。。所以寫了這篇部落格,希望能夠幫到大家

既然這三個方法是一定要重寫的,那為毛我們不定義一個BaseAdpter類呢,然後讓所有的Adapter來繼承這個BaseAdapter類,省去了多餘的程式碼,下面看我是怎麼定義這個BaseAdapter的,看程式碼:

public abstract class BaseAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter {

    private static final String TAG = "BaseAdapter";
    private static final int HEADER_VIEW = 0x1001;
    private static final int FOOTER_VIEW = 0x1002;

    private View headerView;
    private View footerView;

    @Override
    public int getItemViewType(int position) {
        if (position == 0 && hasHeaderView()) {
            return HEADER_VIEW;
        }
        if (position == getItemCount() - 1 && hasFooterView()) {
            return FOOTER_VIEW;
        }
        //如果既不是頭部View,也不是尾部View,那就讓使用者去判斷,該View到底是什麼type
        return getViewType(position);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == HEADER_VIEW) {
            return new EmptyViewHolder(headerView);
        }
        if (viewType == FOOTER_VIEW) {
            return new EmptyViewHolder(footerView);
        }
        return onCreateHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int type = getItemViewType(position);
        if (type == HEADER_VIEW) {
            return;
        }
        if (type == FOOTER_VIEW) {
            return;
        }
        onBindHolder((VH) holder, position);
    }

    public void addHeaderView(View headerView) {
        this.headerView = headerView;
    }

    public void removeHeaderView() {
        this.headerView = null;
    }

    public void addFooterView(View footerView) {
        this.footerView = footerView;
    }

    public void removeFooterView() {
        this.footerView = null;
    }

    public boolean hasHeaderView() {
        return headerView == null ? false : true;
    }

    public boolean hasFooterView() {
        return footerView == null ? false : true;
    }

    //如果使用者不指定,預設的型別就是0
    public int getViewType(int position) {
        return 0;
    }

    abstract VH onCreateHolder(ViewGroup parent, int viewType);

    abstract void onBindHolder(VH holder, int position);
}

為了方便,我就直接把所有程式碼貼上來了,來,聽我慢慢道來~~~

我這個BaseAdapter是可以新增Header和Footer的,用到了泛型和抽象類,看不懂的沒關係,就當泛型不存在就好了,自己腦子裡把泛型替換成一個具體的類就好了

先說一下執行順序吧,getItemViewTyoe先執行,然後返回一個type,然後去執行onCreateViewHolder,這個方法會根據傳過來的type來初始化相應的Holder

打個比方,如果傳過來的type是HEADER_VIEW,就會去例項化EmptyViewHolder,如果傳過來的type是美女,那就會去例項化BeautyHolder,雖然我們這裡沒有美女Holder。BeautyHolder裡面有一些屬性,比如年齡,身高,體重,三圍,愛好,婚否什麼的,都會在這個時候初始化,注意,這一步只是用來確定某個Holder有哪些屬性,並不會給屬性值賦予初始化,用程式碼就是就是這一步只是進行了findViewById操作,其他操作都不會進行。初始化之後會把這個BeautyHolder傳給onBindViewHolder這個方法,這個方法幹什麼的呢,這個方法就是初始化這些屬性的值得,比如三圍是25,65,25,體重是80KG,愛好是刮腿毛什麼的,都初始化好之後,整個View也就呈現在我們的介面上了。。。

Header表示整個Adapter的頭部View,Footer表示整個Adapter的底部View,可以新增,也可以刪除

我再解釋一下那幾個抽象方法,onCreateHolder是這麼滴,假如某個View的型別既不是header,也不是footer,那我們的onCreateHolder就不知道到底該初始化哪個Holder了,於是就寫了一個抽象的方法,交給子類去實現,具體是哪個Holder,這個依據業務邏輯定,這麼寫的話比較靈活的

onBindHolder方法也是,當BaseAdapter不知道怎麼辦的時候,就讓子類去做

具體使用的話只要複製這個BaseAdapter類,然後讓其他類繼承這個類就好了,以後我會慢慢完善這個類,讓它擁有更多的功能。主要還是為了方便開發吧

程式碼的話還是要好好琢磨的,畢竟裡面有幾個抽象方法,還使用到了泛型,我自己寫出來感覺沒啥,能看懂,但你們看可能有點繞。

希望持續關注我的部落格,有不懂得可以在下方留言,我會盡力幫助你,原始碼和相應的demo會在後期更新,想要的同學可以留意一下。

天天加班,也是沒誰了。公司裡的人都走光了,就剩我了,寫完這篇部落格,上傳之後我要趕緊回家睡覺了,十一快到了,預祝大家國慶節快樂~~~~