|
1 | 1 | package com.artshell.arch.widget.rv; |
2 | 2 |
|
| 3 | +import android.annotation.SuppressLint; |
3 | 4 | import android.arch.lifecycle.MutableLiveData; |
4 | 5 | import android.arch.paging.DataSource; |
5 | 6 | import android.arch.paging.PageKeyedDataSource; |
6 | 7 | import android.arch.paging.PagedList; |
7 | 8 | import android.support.annotation.NonNull; |
8 | 9 |
|
| 10 | +import com.artshell.arch.common.EmptyDataException; |
| 11 | +import com.artshell.arch.common.FetchFailedException; |
| 12 | +import com.artshell.arch.common.NoMoreDataException; |
9 | 13 | import com.artshell.arch.storage.Resource; |
10 | 14 | import com.artshell.arch.storage.server.model.HttpPagingResult; |
| 15 | +import com.artshell.arch.storage.server.model.Pageable; |
11 | 16 |
|
| 17 | +import java.util.Collections; |
| 18 | +import java.util.List; |
12 | 19 | import java.util.concurrent.Executor; |
13 | 20 |
|
14 | 21 | import io.reactivex.Flowable; |
15 | 22 | import io.reactivex.Scheduler; |
16 | 23 | import io.reactivex.schedulers.Schedulers; |
17 | 24 |
|
18 | 25 | /** |
19 | | - * @param <Key> 页码(第1页,第2页等) |
20 | | - * @param <Value> {@link PagedList} 最终得到结果 |
| 26 | + * @param <Value> {@link PagedList}的结果类型 |
21 | 27 | * @param <Response> 服务器端返回的json字符串 |
22 | 28 | */ |
23 | | -public abstract class PageableDataSourceFactory<Key extends Integer, Value, Response extends HttpPagingResult> |
24 | | - extends DataSource.Factory<Key, Value> { |
| 29 | +public abstract class PageableDataSourceFactory<Value, Response extends HttpPagingResult<Value>> extends DataSource.Factory<Integer, Value> { |
25 | 30 |
|
26 | | - private MutableLiveData<Resource<Value>> mNetworkState; /* 网络状态(这里并不用来传递获取成功的结果) */ |
27 | | - private PageState mState; /* 分页算法 */ |
28 | | - protected Scheduler mNetworkScheduler; |
| 31 | + /* 网络状态(这里并不用来传递获取成功的结果, 只传递正在加载/加载失败状态) */ |
| 32 | + private MutableLiveData<Resource<Void>> mNetworkState; |
29 | 33 |
|
30 | | - public PageableDataSourceFactory(Executor networkExecutor) { |
| 34 | + private Executor retryExecutor; |
| 35 | + protected Scheduler mNetworkScheduler; |
| 36 | + |
| 37 | + /* 持有一个重试引用 */ |
| 38 | + private Runnable retry; |
| 39 | + |
| 40 | + public PageableDataSourceFactory(Executor workerExecutor) { |
31 | 41 | mNetworkState = new MutableLiveData<>(); |
32 | | - mState = new PageState(); |
33 | | - mNetworkScheduler = Schedulers.from(networkExecutor); |
| 42 | + retryExecutor = workerExecutor; |
| 43 | + mNetworkScheduler = Schedulers.from(workerExecutor); |
34 | 44 | } |
35 | 45 |
|
36 | | - public MutableLiveData<Resource<Value>> getNetworkState() { |
| 46 | + public MutableLiveData<Resource<Void>> getNetworkState() { |
37 | 47 | return mNetworkState; |
38 | 48 | } |
39 | 49 |
|
| 50 | + /** |
| 51 | + * 重试 |
| 52 | + */ |
| 53 | + public void retryFailed() { |
| 54 | + Runnable prevRetry = retry; |
| 55 | + retry = null; |
| 56 | + if (prevRetry != null) { |
| 57 | + retryExecutor.execute(prevRetry); |
| 58 | + } |
| 59 | + } |
| 60 | + |
40 | 61 | @Override |
41 | | - public DataSource<Key, Value> create() { |
42 | | - return null; |
| 62 | + public DataSource<Integer, Value> create() { |
| 63 | + return new PageableDataSource(); |
43 | 64 | } |
44 | 65 |
|
45 | | - /** |
46 | | - * 获取初始分页数据/加载下一页 |
47 | | - */ |
48 | | - private class PageableDataSource extends PageKeyedDataSource<Key, Response> { |
| 66 | + private class PageableDataSource extends PageKeyedDataSource<Integer, Value> { |
49 | 67 |
|
50 | | - @Override |
51 | | - public final void loadInitial(@NonNull PageKeyedDataSource.LoadInitialParams<Key> params, @NonNull LoadInitialCallback<Key, Response> callback) { |
| 68 | + private PageState mState; /* 分页算法 */ |
| 69 | + |
| 70 | + private PageableDataSource() { |
| 71 | + this(new PageState()); |
| 72 | + } |
52 | 73 |
|
| 74 | + private PageableDataSource(PageState state) { |
| 75 | + mState = state; |
53 | 76 | } |
54 | 77 |
|
| 78 | + /** |
| 79 | + * 获取第一页数据 & 计算分页信息 |
| 80 | + * @param params |
| 81 | + * @param callback |
| 82 | + */ |
| 83 | + @SuppressLint("CheckResult") |
55 | 84 | @Override |
56 | | - public final void loadBefore(@NonNull LoadParams<Key> params, @NonNull LoadCallback<Key, Response> callback) { |
57 | | - // 不在某一页之前插入数据,故此忽略实现 |
| 85 | + public final void loadInitial(@NonNull PageKeyedDataSource.LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, Value> callback) { |
| 86 | + source(1) |
| 87 | + .doOnSubscribe(subscription -> mNetworkState.postValue(Resource.loading())) |
| 88 | + .subscribe( |
| 89 | + response -> { |
| 90 | + Pageable<Value> pageableData = response.getPageData(); |
| 91 | + String total = pageableData.getTotal(); |
| 92 | + List<Value> dataList = pageableData.getList() == null ? Collections.emptyList() : pageableData.getList(); |
| 93 | + if ("".equals(total) || "0".equals(total) || dataList.isEmpty()) { |
| 94 | + mNetworkState.postValue(Resource.error(new EmptyDataException("无数据"))); |
| 95 | + } |
| 96 | + // 计算分页状态 |
| 97 | + mState.clear(); |
| 98 | + mState.calculate(Integer.valueOf(total)); |
| 99 | + |
| 100 | + // 回传结果, 设置上一页/下一页的页码 |
| 101 | + callback.onResult(dataList, 1, mState.hasNext() ? mState.getCurrPage() + 1 : null /* 没有下一页 */); |
| 102 | + }, throwable -> { |
| 103 | + retry = () -> loadInitial(params, callback); |
| 104 | + mNetworkState.postValue(Resource.error(throwable)); |
| 105 | + }); |
58 | 106 | } |
59 | 107 |
|
60 | 108 | @Override |
61 | | - public final void loadAfter(@NonNull LoadParams<Key> params, @NonNull LoadCallback<Key, Response> callback) { |
| 109 | + public final void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Value> callback) { |
| 110 | + // 不在某一页之前插入数据,故此忽略实现 |
| 111 | + } |
62 | 112 |
|
| 113 | + /** |
| 114 | + * 获取下一页数据 |
| 115 | + * @param params |
| 116 | + * @param callback |
| 117 | + */ |
| 118 | + @SuppressLint("CheckResult") |
| 119 | + @Override |
| 120 | + public final void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Value> callback) { |
| 121 | + if (params.key == null) { |
| 122 | + mNetworkState.postValue(Resource.error(new NoMoreDataException("没有更多数据"))); |
| 123 | + return; |
| 124 | + } |
| 125 | + source(params.key) |
| 126 | + .doOnSubscribe(subscription -> mNetworkState.postValue(Resource.loading())) |
| 127 | + .subscribe( |
| 128 | + response -> { |
| 129 | + Pageable<Value> pageableData = response.getPageData(); |
| 130 | + String total = pageableData.getTotal(); |
| 131 | + List<Value> dataList = pageableData.getList() == null ? Collections.emptyList() : pageableData.getList(); |
| 132 | + if ("".equals(total) || "0".equals(total) || dataList.isEmpty()) { |
| 133 | + retry = () -> loadAfter(params, callback); |
| 134 | + mNetworkState.postValue(Resource.error(new FetchFailedException("获取数据失败"))); |
| 135 | + } else { |
| 136 | + // 设置当前页 |
| 137 | + mState.setCurrPage(mState.getCurrPage() + 1); |
| 138 | + |
| 139 | + // 回传结果, 设置下一页的页码 |
| 140 | + callback.onResult(dataList, mState.hasNext() ? mState.getCurrPage() + 1 : null /* 没有下一页 */); |
| 141 | + } |
| 142 | + }, throwable -> { |
| 143 | + retry = () -> loadAfter(params, callback); |
| 144 | + mNetworkState.postValue(Resource.error(throwable)); |
| 145 | + }); |
63 | 146 | } |
64 | 147 | } |
65 | 148 |
|
66 | 149 | /** |
67 | | - * @param currentPage 当前页 |
68 | | - * @param <Key> 页码(第1页,第2页等) |
69 | | - * @param <Response> 服务器端返回的json字符串 |
| 150 | + * 获取第一页/下一页数据 |
| 151 | + * @param nextPage 下一页 |
70 | 152 | * @return |
71 | 153 | */ |
72 | | - abstract <Key, Response> Flowable<Response> source(Key currentPage); |
| 154 | + public abstract Flowable<Response> source(Integer nextPage); |
73 | 155 | } |
0 commit comments