1. 程式人生 > >安卓專案實戰之:開源框架BaseRecyclerViewAdapterHelper的使用

安卓專案實戰之:開源框架BaseRecyclerViewAdapterHelper的使用

新增依賴

1,在Project的build.gradle檔案下新增:

allprojects {
        repositories {
            ...
            maven { url "https://jitpack.io" }
        }
    }

2,在app的build.gradle檔案中新增:

dependencies {
            ......
            compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.42'
}

此處注意雖然GitHub上最新版本為43,但是引入2.9.43會有問題,因為該版本是基於AndroidX的。

最基本使用,減少Adapter中70%的程式碼

效果如下:
在這裡插入圖片描述
1,先有資料實體模型,即Bean:

public class Model {
    private String title;
    private String content;
    private String imgUrl;

    //生成set、get方法
    ......
}

2,在佈局檔案中引入RecycleView:

<?xml version="1.0"
encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent"
android:layout_height="wrap_content" /> </RelativeLayout>

3,列表中每一項的佈局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="5dp">

    <ImageView
        android:id="@+id/iv_img"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:scaleType="centerCrop"/>

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:layout_toRightOf="@+id/iv_img"
        android:text="我是標題"
        android:textColor="#f00"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_title"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:layout_toRightOf="@id/iv_img"
        android:text="我是描述" />
</RelativeLayout>

4,編寫介面卡Adapter,同時支援重寫onAttachedToRecyclerView方法,通過getSpanSize來實現具有不同尺寸item的動態佈局。

public class MyAdapter extends BaseQuickAdapter<Model, BaseViewHolder> {

    public MyAdapter(@LayoutRes int layoutResId, @Nullable List<Model> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, Model item) {
        //可鏈式呼叫賦值
        helper.setText(R.id.tv_title, item.getTitle())
                .setText(R.id.tv_content, item.getContent());
        // 設定圖片
        Glide.with(mContext).load(item.getImgUrl()).into((ImageView) helper.getView(R.id.iv_img));

        //獲取當前item的position
        //int position = helper.getLayoutPosition();
    }
}

繼承:從上面可以看出我們需要繼承BaseQuickAdapter,其中兩個泛型,第一個泛型Status是資料實體型別,第二個BaseViewHolder是ViewHolder其目的是為了支援擴充套件ViewHolder。
賦值:可以直接使用viewHolder物件點相關方法通過傳入viewId和資料進行,方法支援鏈式呼叫。如果是載入網路圖片或自定義view可以通過viewHolder.getView(viewId)獲取該控制元件,如果佈局中包含第三方控制元件如Banner,那麼也是通過該方式獲取該控制元件Banner banner = holder.getView(R.id.banner),例如:

    @Override
    protected void convert(BaseViewHolder viewHolder, Status item) {
        viewHolder.setText(R.id.tweetName, item.getUserName())
                .setText(R.id.tweetText, item.getText())
                .setText(R.id.tweetDate, item.getCreatedAt())
                .setVisible(R.id.tweetRT, item.isRetweet())
                .linkify(R.id.tweetText);
                 Banner banner = viewHolder.getView(R.id.banner); // 獲取第三方banner
                 Glide.with(mContext).load(item.getUserAvatar()).crossFade().into((ImageView) viewHolder.getView(R.id.iv));
    }

5,Activity中程式碼:

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private List<Model> datas;
    private MyAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //初始化RecyclerView
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

        //模擬的資料(實際開發中一般是從網路獲取的)
        datas = new ArrayList<>();
        Model model;
        for (int i = 0; i < 15; i++) {
            model = new Model();
            model.setImgUrl("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2516392654,826153290&fm=26&gp=0.jpg");
            model.setTitle("我是第" + i + "條標題");
            model.setContent("第" + i + "條內容");
            datas.add(model);
        }

        //建立佈局管理
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);

        //建立介面卡
        adapter = new MyAdapter(R.layout.item_rv, datas);

        //給RecyclerView設定介面卡
        recyclerView.setAdapter(adapter);
    }
}

新增分割線

自定義線性佈局通用的分割線類DividerItemDecoration:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent) {
//        Log.v("recyclerview - itemdecoration", "onDraw()");

        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }

    }


    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

使用如下:

// 新增分割線
recyclerView.addItemDecoration(new DividerItemDecoration(this,
                DividerItemDecoration.VERTICAL_LIST));

該分隔線是系統預設的,如果要修改該分割線的樣式,可以這樣做,在Application指定的Style樣式中新增:

<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
      ...
      <item name="android:listDivider">@drawable/divider_bg</item>  
</style>

然後自己寫個drawable即可,例如:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:height="1dp" />
    <solid android:color="@color/red" />
</shape>

自定義網格佈局通用的分割線DividerGridItemDecoration:

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
    private Drawable mDivider;

    public DividerGridItemDecoration(Context context)
    {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)
    {

        drawHorizontal(c, parent);
        drawVertical(c, parent);

    }

    private int getSpanCount(RecyclerView parent)
    {
        // 列數
        int spanCount = -1;
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {

            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        }
        return spanCount;
    }

    public void drawHorizontal(Canvas c, RecyclerView parent)
    {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent)
    {
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);

            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
                                int childCount)
    {
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
            if ((pos + 1) % spanCount == 0)// 如果是最後一列,則不需要繪製右邊
            {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL)
            {
                if (
            
           

相關推薦

專案實戰開源框架BaseRecyclerViewAdapterHelper的使用

新增依賴 1,在Project的build.gradle檔案下新增: allprojects { repositories { ... maven { url "https://jitpack.io" }

專案實戰最實用的Retrofit2+RxJava2+MVP框架搭建,避免各種記憶體洩漏

工程目錄結構 目前網上的mvp框架大多存在以下問題: 1,Presenter持有View的引用,容易導致出現記憶體洩漏 MvpPresenter mvpPresenter = new MvpPresenter(this); // 不推薦這樣寫,持有activty引用,容易出現

專案實戰最實用的載入中、無網路、無資料、出錯四種情況切換庫的使用總結

效果圖 錄出來的效果不是很好,真機上展示效果還算完美。 如圖所示該效果的實現依賴三個庫: 1,頂部Tab導航:比TabLayout功能更強大的FlycoTabLayout,具體使用檢視本人之前部落格:安卓專案實戰之:FlycoTabLayout和FlycoRoundView的介紹及

專案實戰ToolBar的使用介紹

ToolBar簡介 Toolbar是谷歌在2014年Google IO 大會上推出的一套全新的設計規範Material Design中的控制元件之一,主要是用來在android 5.0之後代替Android傳統的標題欄ActionBar的,引入在android-support-v7相

專案實戰7.0優化下的全域性網路連線狀態監聽

須知:Android7.0起網路變化監聽隱式廣播被關閉 在 Android 7.0 版本中除了提供諸多多視窗支援、活動通知、後臺優化、訊息傳遞服務和Vulkan 等新特性和功能外,還對系統和 API 行為做出了各種變更,其中最重要的一點:Android7.0為了進行後臺的優化刪除了三

專案實戰幫你從Glide3過渡到Glide4的完美攻略

Glide4:Glide3的優化版 相比於Glide 3 而言,Glide4並不能算是有什麼突破性的升級,而更多的是一些API工整方面的優化,相比於Glide3的API,Glide4進行了更加科學合理的調整,使得易讀性,易寫性,可擴充套件性等方面都有了不錯的提升,但如果你已經對Glide

專案實戰強大的網路請求框架okGo使用詳解(六)擴充套件專案okServer,更強大的下載上傳功能,支援斷點和多工管理

OkGo與OkDownload的區別就是,OkGo只是簡單的做一個下載功能,不具備斷點下載,暫停等操作,但是這在很多時候已經能滿足需要了。 而有些app需要有一個下載列表的功能,就像迅雷下載一樣,每個下載任務可以暫停,可以繼續,可以重新下載,可以有下載優先順序,這時候OkDownload就有

專案實戰強大的網路請求框架okGo使用詳解(五)擴充套件專案okRx,完美結合RxJava

前言 在第一篇講解okGo框架新增依賴支援時,還記得我們額外新增的兩個依賴嗎,一個okRx和一個okServer,這兩個均是基於okGo框架的擴充套件專案,其中okRx可以使請求結合RxJava一起使用,而okServer則提供了強大的下載上傳功能,如斷點支援,多工管理等,本篇我們主要講

專案實戰強大的網路請求框架okGo使用詳解(四)Cookie的管理

Cookie概念相關 具體來說cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在伺服器端保持狀態的方案。同時我們也看到,由於採用伺服器端保持狀態的方案在客戶端也需要儲存一個標識,所以session機制是需要藉助於cookie機制來達到儲存標識的目的,所謂ses

專案實戰強大的網路請求框架okGo使用詳解(三)快取的使用

相關實體類必須實現序列化介面 使用快取前,必須讓涉及到快取javaBean物件實現Serializable介面,否者會報NotSerializableException。因為快取的原理是將物件序列化後直接寫入資料庫中,如果不實現Serializable介面,會導致物件無法序列化,進而無法

專案實戰強大的網路請求框架okGo使用詳解(二)深入理解Callback自定義JsonCallback

前言 JSON是一種取代XML的資料結構,和xml相比,它更小巧但描述能力卻不差,由於它的小巧所以網路傳輸資料將減少更多流量從而加快了傳輸速度,目前客戶端伺服器返回的資料大多都是基於這種格式的,相應的我們瞭解的關於json的解析工具主要有兩個:Gson(Google官方出的)和fas

專案實戰強大的網路請求框架okGo使用詳解(一)實現get,post基本網路請求,下載上傳進度監聽以及對Callback自定義的深入理解

1.新增依賴 //必須使用 compile 'com.lzy.net:okgo:3.0.4' //以下三個選擇新增,okrx和okrx2不能同時使用,一般選擇新增最新的rx2支援即可 compile 'com.lzy.net:okrx:1.0.2' compile 'com.lzy

專案實戰Glide 3高手養成(三)Glide的回撥與監聽

前言 通過前面兩篇的講解,我們對於Glide的一些使用都有了基本瞭解,知道了使用Glide載入圖片只需要一行程式碼即可: Glide.with(this).load(url).into(imageView); 而在這一行程式碼的背後,Glide幫我們執行了成千上萬行的邏輯。

專案實戰Glide 3高手養成(二)Glide強大的圖片變換功能

使用Glide時普遍會遇到的一個問題,如何解決? 首先我們嘗試使用Glide來載入一張圖片,圖片URL地址是:https://www.baidu.com/img/bd_logo1.png 這是百度首頁logo的一張圖片,圖片尺寸是540*258畫素。 接下來我們編寫一個非常簡單的佈局檔案

專案實戰Glide 3高手養成(一)Glide的基本使用

前言 現在Android上的圖片載入框架非常成熟,從最早的老牌圖片載入框架UniversalImageLoader,到後來Google推出的Volley,再到後來的新興軍Glide和Picasso,當然還有Facebook的Fresco。每一個都非常穩定,功能也都十分強大。但是它們的使用

專案實戰與UI那點事圖片適配你必須要了解的知識點

1,mipmap和drawable的區別 在Android4.2以上的版本中,提供了對mipmaps的支援,如果你用Andorid Studio開發Android程式會發現Android Studio自動幫你建立了幾個mipmaps資料夾,很多人每次新建一個工程的時候,總是先把mipma

專案實戰資料庫框架LitePal的使用詳解

LitePal簡介 LitePal是一款開源的Android資料庫框架,它採用了物件關係對映(ORM)的模式,並將我們平時開發最常用到的一些資料庫功能進行了封裝,使得不用編寫一行SQL語句就可以完成各種建表和增刪改查的操作,並且LitePal很“輕”,jar包大

專案實戰Gif圖片載入的最佳實踐android-gif-drawable開源庫的使用

前言 在平時的專案開發中,我們或多或少會遇到載入gif圖片這樣的需求,但是Android的ImageView又無法直接載入Gif圖片,面對這樣的需求我們一般都會想到使用支援載入gif動圖的Glide第三方庫來進行實現,但是使用過程中發現Glide在載入大的gif

專案實戰關於獲取SD卡指定路徑和檔案的講解

前言 當我們將手機連線到電腦上時,我們發現在SD卡的根目錄下生成了成百上千的由各種應用程式建立的資料夾,導致我們也不知道哪個資料夾是用來幹嘛的,這正因為這樣安卓開發人員經常受到使用者的吐槽。 的確作為一個安卓開發者,我們的確不應該將我們應用的資料直接存到SD卡的根目錄下,這樣當手機安

專案實戰Activity啟動過程中動態獲取元件寬高的3種方式

前言 有時候我們需要在Activity啟動的時候獲取某一元件的寬或者是高用於動態的更改UI佈局,但是這時候我們直接通過getWidth和getHeight方法獲取是有問題的,如下: 我們在Activity的onCreate方法中呼叫如下的方法來獲取元件的寬高: /** * 在onC