自定义Paging分页

废话不多说上代码

package com.mgo.basemodule.common.manager.paging;

import android.annotation.SuppressLint;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.mgo.logimpl.MyLog;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.Scheduler;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

/**
 * @package com.mgo.mainmodule.viewmodel2
 * @user by lvyaodong
 * @date 2020/8/27
 * @email [email protected]
 */
public class Paging<T extends PagingDataBase, D> {

    private static final String TAG = "Paging";
    private Scheduler mLoopScheduler;
    //发射数据
    private MutableLiveData<List<D>> postValue = new MutableLiveData<>();
    //数据转换
    private Converter<T, D> converter;
    //页面切换监听
    private OnPageChangerListener mOnPageChangerListener;

    //每页多少个数据
    private int SIZE = -1;


    //数据
    private List<T> mData;
    //总共有几页
    private int mPageCount = 0;
    //当前位于第几页
    private int mCurPage = 0;
    //总的数据大小
    private int mDataSize = 0;

    //多长时间发射一次数据 这个先不实现 先交给外部
    private long mChangeTime = 10 * 1000;

    private Disposable mSubscribe;

    private Paging() {
        mLoopScheduler = Schedulers.from(Executors.newFixedThreadPool(2));
    }

    public Paging(Converter<T, D> converter, int SIZE) {
        this();
        this.converter = converter;
        this.SIZE = SIZE;
    }

    public int getPageCount() {
        return mPageCount;
    }

    public int getCurPage() {
        return mCurPage;
    }

    public void setChangeTime(long mChangeTime) {
        this.mChangeTime = mChangeTime;
    }

    public void setSize(int size) {
        this.SIZE = size;
    }

    public void setConverter(Converter<T, D> converter) {
        this.converter = converter;
    }

    public void setOnPageChangerListener(OnPageChangerListener mOnPageChangerListener) {
        this.mOnPageChangerListener = mOnPageChangerListener;
    }

    public void setDataSource(List<T> data) {
        if (SIZE <= 0) {
            MyLog.d(TAG, "You should set SIZE first");
            return;
        }

        if (converter == null) {
            MyLog.d(TAG, "You should set data converter first");
            return;
        }

        this.mData = data;
        this.mCurPage = 0;
        this.mDataSize = 0;
        this.mPageCount = 0;
        loadData(data);
    }

    public LiveData<List<D>> getPostValue() {
        return postValue;
    }

    /**
     * 可循环下一页
     *
     * @return 返回是否为最后一页
     */
    public boolean nextPageWithLoop() {
        if (nextPage()) {
            MyLog.d(TAG, "Start from first page!");
            firstPage();
            return true;
        }
        return false;
    }

    /**
     * 不可循环下一页
     *
     * @return
     */
    public boolean nextPage() {
        MyLog.d(TAG, "Try execute next page.");

        if (mPageCount == 0) {
            MyLog.d(TAG, "No data,no page!");
            return true;
        }

        if (mCurPage >= mPageCount - 1) {
            MyLog.d(TAG, "It's already the last page.");
            return true;
        }
        int start = (++mCurPage) * SIZE;
        int end = Math.min((mCurPage + 1) * SIZE, mDataSize);

        MyLog.d(TAG, "Execute next page success. start: " + start + "--> end: " + end + ", curPage: " + mCurPage);
        postPageChange(start, end);

        if (mOnPageChangerListener != null) {
            mOnPageChangerListener.onPageChange(mCurPage);
        }
        return false;
    }

    /**
     * 上一页
     */
    public void prePage() {
        MyLog.d(TAG, "Try execute pre page.");
        if (mPageCount == 0) {
            MyLog.d(TAG, "No data,no page!");
            return;
        }
        if (mCurPage <= 0) {
            MyLog.d(TAG, "It's already the first page.");
            return;
        }

        int end = Math.min(mCurPage * SIZE, mDataSize);
        int start = (--mCurPage) * SIZE;

        MyLog.d(TAG, "Execute pre page success. start: " + start + "--> end: " + end + ", curPage: " + mCurPage);
        postPageChange(start, end);
        if (mOnPageChangerListener != null) {
            mOnPageChangerListener.onPageChange(mCurPage);
        }
    }

    @SuppressLint("DefaultLocale")
    public void skipToSomePage(int page) {
        MyLog.d(TAG, String.format("Try skip to '%d' page.", page));
        if (mPageCount == 0) {
            MyLog.d(TAG, "No data,no page!");
            return;
        }

        if (page > mPageCount - 1 || page < 0) {
            MyLog.d(TAG, String.format("No '%d' page! Please re-skip! Page should be 0<=page<=mPageCount - 1", page));
            return;
        }

        mCurPage = page;

        int start = mCurPage * SIZE;
        int end = (++mCurPage) * SIZE;
        end = Math.min(end, mDataSize);
        MyLog.d(TAG, "Execute next page success. start: " + start + "--> end: " + end + ", curPage: " + mCurPage);
        postPageChange(start, end);

        if (mOnPageChangerListener != null) {
            mOnPageChangerListener.onPageChange(mCurPage);
        }
    }


    public void startLoop() {
        if (mChangeTime <= 0) {
            MyLog.d("Please set time first!");
            return;
        }
        cancelLoop();
        mSubscribe = Flowable.interval(mChangeTime, mChangeTime, TimeUnit.MILLISECONDS)
                .subscribeOn(mLoopScheduler)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(aLong -> nextPageWithLoop());
    }

    public void cancelLoop() {
        dispose(mSubscribe);
    }


    private void loadData(List<T> data) {
        if (data == null || data.size() <= 0) {
            MyLog.d(TAG, "no data source!");
            return;
        }

        //计算数据量
        mDataSize = data.size();
        //页数
        int page = mDataSize / SIZE;
        MyLog.d(TAG, "page:" + page);
        if (mDataSize % SIZE == 0) {
            this.mPageCount = page;
        } else {
            this.mPageCount = page + 1;
        }
        MyLog.d(TAG, "PageCount:" + mPageCount);
        //为每个数据添加具体数据位置
        for (int i = 0; i < mDataSize; i++) {
            data.get(i).setPagItemIndex(i);
        }

        if (mOnPageChangerListener != null) {
            mOnPageChangerListener.pagingInitDone(mPageCount);
        }

        //发射第一页数据
        firstPage();
    }

    private void firstPage() {
        if (mPageCount == 0) {
            MyLog.d(TAG, "FirstPage PageCount:" + mPageCount);
            return;
        }

        if (converter == null) {
            MyLog.d(TAG, "You should set data converter first");
            return;
        }
        MyLog.d(TAG, "Post first page datas!");
        mCurPage = 0;
        postValue.postValue(converter.convertData(mData.subList(0, Math.min(mDataSize, SIZE))));
        if (mOnPageChangerListener != null) {
            mOnPageChangerListener.onPageChange(mCurPage);
        }
    }

    private void postPageChange(int pageNum, int size) {
        if (converter == null) {
            MyLog.d(TAG, "You should set data converter first");
            return;
        }
        postValue.postValue(converter.convertData(mData.subList(pageNum, size)));
    }

    public interface Converter<T, D> {
        List<D> convertData(List<T> data);
    }

    public interface OnPageChangerListener {
        void onPageChange(int curPage);

        void pagingInitDone(int pageCount);
    }

    private void dispose(Disposable disposable) {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }

}



public class PagingDataBase implements Serializable {

    private int pagItemIndex;

    public int getPagItemIndex() {
        return pagItemIndex;
    }

    public void setPagItemIndex(int pagItemIndex) {
        this.pagItemIndex = pagItemIndex;
    }
}

其实就是将数据源传入,自己处理数据然后借助LiveData把数据发射出去。内部用RxJava实现了自动翻页处理,如果能实现一个LifeCycle实现自动销毁自动翻页,就更好了。

考虑后期优化:

  • 增加LifeCycle,自动销毁自动轮播
  • 去除RxJava重依赖
  • 完善页面翻页方法
    使用:

1、初始化

//两个泛型第一个是传入的数据,第二个是你要转成的数据,这个地方主要是为了能够直接拿到想要的数据,实现Converter数据转换的方法
//第二个参数是要分页的个数 也就是4个一页
Paging<T,D> mPaging = new Paging<>((Paging.Converter<T, D>) data -> data, 4);

2、配置数据

//设置数据后自动发射第一页数据 如果不符合你的需求可以自己去修改源码
mPaging.setDataSource(data);

3、下一页上一页数据

//下一页数据
mPaging.nextPage()
//上一页数据
mPaging.prePage()

4.下一页数据,自动循环(如果当前页是最后一页下一页没有数据则从头开始发射第一页数据)

//下一页数据
mPaging.nextPageWithLoop()

5.跳到某一页

//这个添加后未测试过
mPaging.skipToSomePage(int page)

6.数据监听

mPaging.getPostValue().observe(this, entWxAppBeans -> {
            //收到数据
        });

7.页面初始化,页面翻页监听

mPaging.setOnPageChangerListener(new Paging.OnPageChangerListener() {
            @Override
            public void onPageChange(int curPage) {
                MyLog.d(TAG, String.format("Page change to %s.", curPage));
              //翻页监听
            }

            @Override
            public void pagingInitDone(int pageCount) {
               //数据加载完成,页面总数回调
            }
        });

猜你喜欢

转载自blog.csdn.net/u011148116/article/details/108666892