- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在我的 fragment 中,我集成了 android jetpack 分页库和数据源,我使用 PageKeyedDataSource 和改造 API 回调。
代码异常运行并将数据加载到 recyclerview 但在我滚动到底部后,它应该通过在数据源类中触发 loadAfter 函数来加载更多数据但它没有
我也切换到 ItemKeyedDataSource 仍然无法执行
是我代码错了还是插件有问题!但在我在 GitHub 中发现的一些演示应用程序中,我遵循了那里的代码,效果很好。如果有人遇到这个问题并解决了请告诉我编辑:使用 AndroidX
public class ReportsDataSource extends PageKeyedDataSource<Integer, ReportItemModel> {
MutableLiveData<NetworkState> networkState = new MutableLiveData<>();
MutableLiveData<NetworkState> initialLoad = new MutableLiveData<>();
private UserService getUserService;
private List<Call<?>> compositeDisposable;
private CompositeDisposable compositeDisposableData;
private SchedulerProvider schedulerProvider;
private Completable retryCompletable = null;
public ReportsDataSource(UserService getUserService, List<Call<?>> compositeDisposable, CompositeDisposable compositeDisposableData, SchedulerProvider schedulerProvider) {
this.getUserService = getUserService;
this.compositeDisposable = compositeDisposable;
this.compositeDisposableData = compositeDisposableData;
this.schedulerProvider = schedulerProvider;
}
@Override
public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, ReportItemModel> callback) {
networkState.postValue(NetworkState.LOADING);
initialLoad.postValue(NetworkState.LOADING);
loadPage(1, new callback() {
@Override
public void get(ReportListModel list) {
setRetry(null);
networkState.postValue(NetworkState.LOADED);
initialLoad.postValue(NetworkState.LOADED);
callback.onResult(list.data.items, 1, list.data.next);
}
@Override
public void failure(Throwable t) {
setRetry(() -> loadInitial(params, callback));
NetworkState error = NetworkState.error(t.getMessage());
networkState.postValue(error);
initialLoad.postValue(error);
}
});
}
@Override
public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, ReportItemModel> callback) {
}
@Override
public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, ReportItemModel> callback) {
networkState.postValue(NetworkState.LOADING);
loadPage(params.key, new callback() {
@Override
public void get(ReportListModel list) {
setRetry(null);
networkState.postValue(NetworkState.LOADED);
callback.onResult(list.data.items, list.data.next != params.key ? null : list.data.next);
}
@Override
public void failure(Throwable t) {
setRetry(() -> loadAfter(params, callback));
networkState.postValue(NetworkState.error(t.getMessage()));
}
});
}
public static void log(String msg) {
boolean threadMain = Looper.getMainLooper().getThread() == Thread.currentThread();
Timber.tag("Thread_finder_" + (threadMain ? "ui" : "none")).d(Thread.currentThread().getId() + " " + msg);
}
private void loadPage(int i, callback callback) {
log("loadPage");
Call<ReportListModel> call = getUserService.getReportsList(i);
compositeDisposable.add(call);
try {
Response<ReportListModel> response = call.execute();
log("onResponse");
if (RetrofitHelper.isSuccessful(response)) {
callback.get(response.body());
} else {
callback.failure(new Throwable("Model verification is failed"));
}
} catch (IOException e) {
callback.failure(e);
//e.printStackTrace();
}
}
public void retry() {
if (retryCompletable != null) {
compositeDisposableData.add(retryCompletable.subscribeOn(schedulerProvider.io()).observeOn(schedulerProvider.ui()).subscribe(() -> {
}, Timber::d));
}
}
private void setRetry(Action action) {
if (action == null) {
this.retryCompletable = null;
} else {
this.retryCompletable = Completable.fromAction(action);
}
}
@NonNull
public MutableLiveData<NetworkState> getNetworkState() {
return networkState;
}
@NonNull
public MutableLiveData<NetworkState> getInitialLoad() {
return initialLoad;
}
public interface callback {
void get(ReportListModel list);
void failure(Throwable t);
}
}
View 模型
public class ReportsListViewModel extends ViewModel {
private static final int PAGE_SIZE = 10;
private Executor executor = Executors.newFixedThreadPool(5);
public LiveData<PagedList<ReportItemModel>> list;
private List<Call<?>> compositeDisposable = new ArrayList<>();
private CompositeDisposable compositeDisposableData = new CompositeDisposable();
private ReportsDataSourceFactory sourceFactory;
public final ObservableBoolean isErrorMessageVisible;
public final ObservableBoolean isRetryButtonVisible;
public final ObservableBoolean isLoadingProgressBarVisible;
public final ObservableBoolean isSwipeRefreshLayoutEnable;
public final ObservableField<String> errorMessage;
public ReportsListViewModel(UserService userService, SchedulerProvider schedulerProvider) {
sourceFactory = new ReportsDataSourceFactory(userService, compositeDisposable, compositeDisposableData, schedulerProvider);
PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(PAGE_SIZE)
.setEnablePlaceholders(false)
.build();
list = new LivePagedListBuilder<>(sourceFactory, config).build();
isErrorMessageVisible = new ObservableBoolean(false);
errorMessage = new ObservableField<>("");
isRetryButtonVisible = new ObservableBoolean(false);
isLoadingProgressBarVisible = new ObservableBoolean(true);
isSwipeRefreshLayoutEnable = new ObservableBoolean(true);
}
@Override
protected void onCleared() {
super.onCleared();
RetrofitStatic.clearRetrofitList(compositeDisposable);
compositeDisposableData.clear();
}
public void retry() {
sourceFactory.getDataSourceLiveData().getValue().retry();
}
public void refresh() {
sourceFactory.getDataSourceLiveData().getValue().invalidate();
}
public LiveData<NetworkState> getNetworkState() {
return Transformations.switchMap(sourceFactory.getDataSourceLiveData(), ReportsDataSource::getNetworkState);
}
public LiveData<NetworkState> getRefreshState() {
return Transformations.switchMap(sourceFactory.getDataSourceLiveData(), ReportsDataSource::getInitialLoad);
}
public void setInitialLoadingState(NetworkState networkState) {
isErrorMessageVisible.set((networkState.getMessage() != null));
errorMessage.set(networkState.getMessage());
isRetryButtonVisible.set(networkState.getStatus() == NetworkStateStatus.FAILED);
isLoadingProgressBarVisible.set(networkState.getStatus() == NetworkStateStatus.RUNNING);
isSwipeRefreshLayoutEnable.set(networkState.getStatus() == NetworkStateStatus.SUCCESS);
}
}
页面列表适配器
public class ReportListAdapter extends PagedListAdapter<ReportItemModel, RecyclerView.ViewHolder> {
public static final DiffUtil.ItemCallback<ReportItemModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<ReportItemModel>() {
@Override
public boolean areItemsTheSame(@NonNull ReportItemModel oldItem, @NonNull ReportItemModel newItem) {
return oldItem.reportId == newItem.reportId;
}
@Override
public boolean areContentsTheSame(@NonNull ReportItemModel oldItem, @NonNull ReportItemModel newItem) {
return oldItem.equals(newItem);
}
};
private NetworkState networkState = null;
private RetryCallback retryCallback;
public ReportListAdapter(RetryCallback retryCallback) {
super(DIFF_CALLBACK);
this.retryCallback = retryCallback;
}
@Override
public int getItemViewType(int position) {
if (hasExtraRow() && position == getItemCount() - 1) {
return R.layout.item_network_state;
} else {
return R.layout.recycler_report_item;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case R.layout.recycler_report_item:
default:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_report_item, parent, false);
return new ViewHolder(view);
case R.layout.item_network_state:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_network_state, parent, false);
return new NetWorkStateHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ViewHolder) {
bindView((ViewHolder) holder, position, holder.itemView.getContext());
} else if (holder instanceof NetWorkStateHolder) {
bindNetworkView((NetWorkStateHolder) holder, position, holder.itemView.getContext());
}
}
private void bindNetworkView(NetWorkStateHolder holder, int position, Context context) {
NetworkStateItemViewModel mNetworkStateItemViewModel = new NetworkStateItemViewModel(networkState, retryCallback);
if (holder.binding != null) {
holder.binding.setViewModel(mNetworkStateItemViewModel);
holder.binding.executePendingBindings();
}
}
@Override
public int getItemCount() {
return super.getItemCount() + (hasExtraRow() ? 1 : 0);
}
private void bindView(ViewHolder holder, int position, Context context) {
holder.binding.reportId.setText( "Report ID: "+position);
}
private boolean hasExtraRow() {
return networkState != null && networkState != NetworkState.LOADED;
}
public void setNetworkState(NetworkState newNetworkState) {
if (getCurrentList() != null) {
if (getCurrentList().size() != 0) {
NetworkState previousState = this.networkState;
boolean hadExtraRow = hasExtraRow();
this.networkState = newNetworkState;
boolean hasExtraRow = hasExtraRow();
if (hadExtraRow != hasExtraRow) {
if (hadExtraRow) {
notifyItemRemoved(super.getItemCount());
} else {
notifyItemInserted(super.getItemCount());
}
} else if (hasExtraRow && previousState != newNetworkState) {
notifyItemChanged(getItemCount() - 1);
}
}
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final RecyclerReportItemBinding binding;
public ViewHolder(@NonNull View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}
}
public class NetWorkStateHolder extends RecyclerView.ViewHolder {
private final ItemNetworkStateBinding binding;
private final NetworkStateItemViewModel mNetworkStateItemViewModel;
public NetWorkStateHolder(@NonNull View itemView) {
super(itemView);
mNetworkStateItemViewModel = new NetworkStateItemViewModel(networkState, retryCallback);
binding = DataBindingUtil.bind(itemView);
binding.setViewModel(mNetworkStateItemViewModel);
binding.executePendingBindings();
}
}
}
fragment :
public class ReportsFragment extends ParentFragment implements RetryCallback {
private ReportsFragment.callback callback;
private FragmentReportsListBinding binding;
private ReportsListViewModel reportViewModel;
private ReportListAdapter adapter;
public void setup(callback callback) {
this.callback = callback;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_reports_list, container, false);
reportViewModel = ViewModelProviders.of(this, mViewModelFactory).get(ReportsListViewModel.class);
binding.setViewModel(reportViewModel);
binding.executePendingBindings();
initAdapter();
initSwipeToRefresh();
return binding.getRoot();
}
private void initSwipeToRefresh() {
reportViewModel.getRefreshState().observe(this, networkState -> {
if (adapter.getCurrentList() != null) {
if (adapter.getCurrentList().size() > 0) {
binding.usersSwipeRefreshLayout.setRefreshing(networkState != null && networkState.getStatus() == NetworkState.LOADING.getStatus());
} else {
setInitialLoadingState(networkState);
}
} else {
setInitialLoadingState(networkState);
}
});
}
private void setInitialLoadingState(NetworkState networkState) {
reportViewModel.setInitialLoadingState(networkState);
}
private void initAdapter() {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
adapter = new ReportListAdapter(this);
binding.recycler.setLayoutManager(linearLayoutManager);
binding.recycler.setAdapter(adapter);
reportViewModel.list.observe(this, adapter::submitList);
reportViewModel.getNetworkState().observe(this, adapter::setNetworkState);
}
@Override
public void retry() {
reportViewModel.retry();
}
public interface callback {
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="dasarahalli.portal.adapters.paging.reports.ReportsListViewModel" />
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/usersSwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:enabled="@{viewModel.isSwipeRefreshLayoutEnable}"
app:onRefreshListener="@{viewModel::refresh}">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/errorMessageTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@{viewModel.errorMessage}"
android:visibility="@{viewModel.isErrorMessageVisible ? View.VISIBLE : View.GONE}" />
<ProgressBar
android:id="@+id/loadingProgressBar"
style="?android:attr/progressBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="@{viewModel.isLoadingProgressBarVisible ? View.VISIBLE : View.GONE}" />
<Button
android:id="@+id/retryLoadingButton"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:onClick="@{() -> viewModel.retry()}"
android:text="RETRY"
android:visibility="@{viewModel.isRetryButtonVisible ? View.VISIBLE : View.GONE}" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
最佳答案
如您所见,在上面的代码中,我没有在 onBindViewHolder 下调用 getitem,但是在我请求 getItem(itemPostion) 之后,它就开始工作了应该是
演示项目:
关于android - PageKeyedDataSource loadAfter 不会启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51354212/
我正在使用 PageKeyedDataSource通过调用 API 和使用 Retrofit 进行分页。 我正在使用 Dagger 2 进行依赖注入(inject)。 @Provides Reposi
我有一个连续调用loadAfter的PageKeyedDataSource,所有的项目都多次添加到Recyclerview中。从 API 方面来看,一个空 lastEvaluatedKey 意味着给我
在我的 fragment 中,我集成了 android jetpack 分页库和数据源,我使用 PageKeyedDataSource 和改造 API 回调。 代码异常运行并将数据加载到 recycl
根据文档,在 UI 线程中创建 PagedList 期间调用 loadInitial 以提供一些占位符,直到获取实际数据以避免向用户显示空列表。 有什么方法可以跳过 loadInitial 或返回空列
我在我的项目中使用 android 架构组件。所以我使用分页库进行分页,在我的情况下,我需要 PageKeyedDataSource,但我无法将加载的数据返回到 UI, 代码是 数据源工厂.kt cl
我是一名优秀的程序员,十分优秀!