【问题标题】:Android Paging library Index out of bound exceptionAndroid分页库索引超出范围异常
【发布时间】:2020-11-01 17:49:33
【问题描述】:

如果所有页面的项目都相同,我正在 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);
        }
    });
}

}

ViewModel 类

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);
}

}

【问题讨论】:

    标签: java android pagination android-paging android-paging-library


    【解决方案1】:

    Paging2 不支持可变页面大小,您需要迁移到 Paging3(仍处于 alpha 阶段)以获得该功能。这部分是由于平铺支持是如何实现的,但是 Paging3 已经从头开始重写了一些东西以消除这个限制。

    【讨论】:

    • 你能附上任何链接或样本吗,因为我正在寻找 10 天后的解决方案
    • 这里有带有示例的文档:developer.android.com/topic/libraries/architecture/paging/…。以及 Github 上的其他示例:github.com/android/architecture-components-samples (PagingSample / PagingWithNetwork)
    • 感谢这个链接......但我想知道在 android 分页库 3 中如何处理可变页面大小?
    • PagingSource 可以返回不同大小的页面,Paging3 会处理它。在 Paging2 中,实际上不支持从 DataSource 返回不同大小的页面,尽管它可能不会在所有情况下都崩溃。尽管您需要迁移到 Paging3 API,但对于可变页面大小不需要额外的代码。有一个 .toPagingSource() 工厂助手可以帮助您进行分段迁移。在我之前发布的 DAC 链接中,还有一个非常详细的迁移指南。
    猜你喜欢
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    相关资源
    最近更新 更多