如果所有页面的项目都相同,我正在 android 中实现分页库一切正常。当最后一页项目的项目大小为 1 而不是 10 时,它会给出异常。我正在使用带有 androidx 的分页库 2.1.1。
例外
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dasfilm.azzeddine.dasfilm, PID: 22472
java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
at java.util.ArrayList.get(ArrayList.java:437)
at androidx.paging.PagedStorage.get(PagedStorage.java:152)
at androidx.paging.PagedList.get(PagedList.java:384)
at androidx.paging.AsyncPagedListDiffer.getItem(AsyncPagedListDiffer.java:206)
at androidx.paging.PagedListAdapter.getItem(PagedListAdapter.java:156)
at com.dasfilm.azzeddine.dasfilm.Views.Adapters.FreshoneProductPaggingAdapter.onBindViewHolder(FreshoneProductPaggingAdapter.java:56)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:286)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:343)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:359)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:366)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:397)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
DataSource 类:这是我的数据源类,用于从 Web 服务获取数据
public class MoviesInTheaterDataSource extends PageKeyedDataSource<Integer, FreshProduct> {
private static final String TAG = "MoviesInTheaterDataSou";
private ProductApiCall tmdbWebService;
private MutableLiveData<NetworkState> networkState;
private MutableLiveData<NetworkState> initialLoading;
private Executor retryExecutor;
public MoviesInTheaterDataSource(Executor retryExecutor,ProductApiCall webService) {
tmdbWebService = webService;
networkState = new MutableLiveData<>();
initialLoading = new MutableLiveData<>();
this.retryExecutor = retryExecutor;
}
public MutableLiveData<NetworkState> getNetworkState() {
return networkState;
}
public MutableLiveData getInitialLoading() {
return initialLoading;
}
@Override
public void loadInitial(@NonNull final LoadInitialParams<Integer> params, @NonNull final LoadInitialCallback<Integer, FreshProduct> callback) {
Log.d(TAG, "loadInitial: ");
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",1);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
@Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
int loadsize = params.requestedLoadSize;
callback.onResult(itemList, 1, 2);
networkState.postValue(NetworkState.LOADED);
}
});
}
@Override
public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, FreshProduct> callback) {
}
@Override
public void loadAfter(@NonNull final LoadParams<Integer> params, @NonNull final LoadCallback<Integer, FreshProduct> callback) {
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",params.key);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
@Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADED);
callback.onResult(itemList, params.key+1);
networkState.postValue(NetworkState.LOADED);
}
});
}
}
数据源工厂类
public class MoviesInTheaterDataSource extends PageKeyedDataSource<Integer, FreshProduct> {
private static final String TAG = "MoviesInTheaterDataSou";
private ProductApiCall tmdbWebService;
private MutableLiveData<NetworkState> networkState;
private MutableLiveData<NetworkState> initialLoading;
private Executor retryExecutor;
public MoviesInTheaterDataSource(Executor retryExecutor,ProductApiCall webService) {
tmdbWebService = webService;
networkState = new MutableLiveData<>();
initialLoading = new MutableLiveData<>();
this.retryExecutor = retryExecutor;
}
public MutableLiveData<NetworkState> getNetworkState() {
return networkState;
}
public MutableLiveData getInitialLoading() {
return initialLoading;
}
@Override
public void loadInitial(@NonNull final LoadInitialParams<Integer> params, @NonNull final LoadInitialCallback<Integer, FreshProduct> callback) {
Log.d(TAG, "loadInitial: ");
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",1);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
@Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
int loadsize = params.requestedLoadSize;
callback.onResult(itemList, 1, 2);
networkState.postValue(NetworkState.LOADED);
}
});
}
@Override
public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, FreshProduct> callback) {
}
@Override
public void loadAfter(@NonNull final LoadParams<Integer> params, @NonNull final LoadCallback<Integer, FreshProduct> callback) {
networkState.postValue(NetworkState.LOADING);
tmdbWebService.getProductList(1,"","",params.key);
tmdbWebService.SetListenersProduct(new ProductApiCall.ListenersProduct() {
@Override
public void onSuccess(List<FreshProduct> itemList, int totalPageCount) {
initialLoading.postValue(NetworkState.LOADING);
networkState.postValue(NetworkState.LOADED);
callback.onResult(itemList, params.key+1);
networkState.postValue(NetworkState.LOADED);
}
});
}
}
视图模型类
public class MoviesInTheaterViewModel extends ViewModel {
private static final String TAG = "TheaterViewModel";
private LiveData<PagedList<FreshProduct>> moviesInTheaterList;
private LiveData<NetworkState> networkStateLiveData;
private Executor executor;
private LiveData<MoviesInTheaterDataSource> dataSource;
public MoviesInTheaterViewModel() {
Log.d(TAG, "MoviesInTheaterViewModel: ");
executor = Executors.newFixedThreadPool(5);
ProductApiCall webService = new ProductApiCall(MyApp.getInstance().getApplicationContext());
MoviesInTheaterDataSourceFactory factory = new MoviesInTheaterDataSourceFactory(executor,webService);
dataSource = factory.getMutableLiveData();
networkStateLiveData = Transformations.switchMap(factory.getMutableLiveData(), new Function<MoviesInTheaterDataSource, LiveData<NetworkState>>() {
@Override
public LiveData<NetworkState> apply(MoviesInTheaterDataSource source) {
Log.d(TAG, "apply: network change");
return source.getNetworkState();
}
});
PagedList.Config pageConfig = (new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(10)
.build();
moviesInTheaterList = (new LivePagedListBuilder<Integer,FreshProduct>(factory,pageConfig))
.setFetchExecutor(executor)
.build();
}
public LiveData<PagedList<FreshProduct>> getMoviesInTheaterList() {
Log.d(TAG, "getMoviesInTheaterList: ");
return moviesInTheaterList;
}
public LiveData<NetworkState> getNetworkStateLiveData() {
return networkStateLiveData;
}
}
活动课
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private MoviesInTheaterViewModel mMoviesViewModel;
private RecyclerView mRecyclerView;
private FreshoneProductPaggingAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: ");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.list);
adapter = new FreshoneProductPaggingAdapter(this);
mMoviesViewModel = ViewModelProviders.of(this).get(MoviesInTheaterViewModel.class);
mMoviesViewModel.getMoviesInTheaterList().observe(this, new Observer<PagedList<FreshProduct>>() {
@Override
public void onChanged(@Nullable PagedList<FreshProduct> movies) {
Log.d(TAG, "onChanged: "+movies.size());
adapter.submitList(movies);
}
});
mMoviesViewModel.getNetworkStateLiveData().observe(this, new Observer<NetworkState>() {
@Override
public void onChanged(@Nullable NetworkState networkState) {
Log.d(TAG, "onChanged: network state changed");
adapter.setNetworkState(networkState);
}
});
mRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false));
mRecyclerView.setAdapter(adapter);
}
}