废话不多说上代码
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) {
//数据加载完成,页面总数回调
}
});