ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

android-PageKeyedDataSource loadAfter不会被触发

2019-10-12 01:38:03  阅读:212  来源: 互联网

标签:android android-jetpack android-paging


在我的片段中,我将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);
    }
}

视图模型

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

PageListAdapter

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

分段:

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)之后,它全部开始工作了,它应该是

示范项目:

androidx-paging-library-demo-java

标签:android,android-jetpack,android-paging
来源: https://codeday.me/bug/20191012/1896869.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有