android paging library - which DataSource I should use

两盒软妹~` 提交于 2019-12-24 08:34:04

问题


What I Want: I want to implement Android Paging Library with network call only.

What I Understood: So, DataSource has three classes that I can extend.

  • PageKeyedDataSource: If your web service has pageNumber in url then you can use it.
  • ItemKeyedDataSource: When you are fetching nested data then you can use it. For example getting replies on particular comment.
  • PositionalDataSource: You can use when you know exact number of data is going to load.

What I Tried : Code is below.

MainActivity.java

    public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView recyclerView = findViewById(R.id.recyclerView);

        final GitHubUserAdapter gitHubUserAdapter = new GitHubUserAdapter();

        GitHubUserViewModel gitHubUserViewModel = ViewModelProviders.of(this).get(GitHubUserViewModel.class);
        gitHubUserViewModel.getLivePagedListData().observe(this, new Observer<PagedList<GitHubUserModel>>() {

            @Override
            public void onChanged(@Nullable PagedList<GitHubUserModel> gitHubUserModels) {
                gitHubUserAdapter.submitList(gitHubUserModels);
            }
        });
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(gitHubUserAdapter);
    }
}

GitHubUserAdapter.java

    public class GitHubUserAdapter extends PagedListAdapter<GitHubUserModel, GitHubUserAdapter.GitHubUserViewHolder> {

    public GitHubUserAdapter() {
        super(DIFF_CALLBACK);
    }

    @NonNull
    @Override
    public GitHubUserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_github_user, parent, false);
        return new GitHubUserViewHolder(layoutView);
    }

    @Override
    public void onBindViewHolder(@NonNull GitHubUserViewHolder holder, int position) {
        holder.tv_user_id.setText(String.valueOf(getItem(position).getId()));
    }

    class GitHubUserViewHolder extends RecyclerView.ViewHolder {

        TextView tv_user_id;

        public GitHubUserViewHolder(View itemView) {
            super(itemView);
            tv_user_id = itemView.findViewById(R.id.tv_user_id);
        }
    }
}

GitHubUserModel.java

    public class GitHubUserModel {

    private String id;

    /*

    Other response variables like avatar_url

     */

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    /*

    Other getter setters for other variables like getAvatar_url() & setAvatar_url()

     */

    public static DiffUtil.ItemCallback<GitHubUserModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<GitHubUserModel>() {
        @Override
        public boolean areItemsTheSame(GitHubUserModel oldItem, GitHubUserModel newItem) {
            return oldItem.id.equalsIgnoreCase(newItem.id);
        }

        @Override
        public boolean areContentsTheSame(GitHubUserModel oldItem, GitHubUserModel newItem) {
            return oldItem.equals(newItem);
        }
    };
}

GitHubUserViewModel.java

    public class GitHubUserViewModel extends ViewModel {

    private Executor mBackgroundThread;
    private LiveData<PagedList<GitHubUserModel>> mGitHubListLiveData;

    private APIEndPoints mApiEndPoints = RetrofitClient.getInstance().create(APIEndPoints.class);

    public GitHubUserViewModel() {
        mBackgroundThread = Executors.newFixedThreadPool(5);
        getDataFromAPI();
    }

    private void getDataFromAPI() {

        DataSource.Factory<Integer, GitHubUserModel> dataSourceFactory = new DataSource.Factory<Integer, GitHubUserModel>() {
            @Override
            public DataSource<Integer, GitHubUserModel> create() {
                GitHubUserDataSource gitHubUserDataSource = new GitHubUserDataSource(mApiEndPoints);
                return gitHubUserDataSource;
            }
        };

        PagedList.Config pagedListConfig = new PagedList.Config.Builder()
                .setPageSize(6)
                .setPrefetchDistance(3)
                .setInitialLoadSizeHint(6)
                .setEnablePlaceholders(true)
                .build();

        mGitHubListLiveData = new LivePagedListBuilder<>(dataSourceFactory, pagedListConfig)
                .setInitialLoadKey(0)
                .setFetchExecutor(mBackgroundThread)
                .build();
    }

    public LiveData<PagedList<GitHubUserModel>> getLivePagedListData() {
        return mGitHubListLiveData;
    }
}

GitHubUserDataSource.java

    public class GitHubUserDataSource extends ItemKeyedDataSource<Integer, GitHubUserModel> {

    private final APIEndPoints mApiEndPoints;

    GitHubUserDataSource(APIEndPoints apiEndPoints) {

        this.mApiEndPoints = apiEndPoints;
    }

    int inRange(int position, int start, int end) {

        if (position < start) return start;
        if (position > end) return end;

        return position;
    }

    @NonNull
    @Override
    public Integer getKey(@NonNull GitHubUserModel gitHubUserModel) {
        return Integer.valueOf(gitHubUserModel.getId());
    }

    @Override
    public void loadInitial(@NonNull final LoadInitialParams<Integer> params, @NonNull final LoadInitialCallback<GitHubUserModel> callback) {

        mApiEndPoints.getGitHubUsers().subscribe(new Observer<List<GitHubUserModel>>() {

            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(List<GitHubUserModel> gitHubUserModels) {

                int pageSize = Math.min(8, params.requestedLoadSize);

                int firstItem = inRange(params.requestedInitialKey == null ? 0 : params.requestedInitialKey,
                        0, gitHubUserModels.size());

                int lastItem = inRange(firstItem + pageSize, 0, gitHubUserModels.size());

                List<GitHubUserModel> gitHubUserModelsToPass;

                if (firstItem == lastItem) {

                    gitHubUserModelsToPass = new ArrayList<>();

                } else {

                    gitHubUserModelsToPass = gitHubUserModels.subList(firstItem, lastItem);
                }

                if (params.placeholdersEnabled) {

                    callback.onResult(gitHubUserModelsToPass, firstItem, gitHubUserModels.size());

                } else {

                    callback.onResult(gitHubUserModelsToPass);
                }
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }

    @Override
    public void loadAfter(@NonNull final LoadParams<Integer> params, @NonNull final LoadCallback<GitHubUserModel> callback) {

        mApiEndPoints.getGitHubUsers().subscribe(new Observer<List<GitHubUserModel>>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(List<GitHubUserModel> gitHubUserModels) {

                int pageSize = Math.min(20, params.requestedLoadSize);
                int firstItem = inRange(params.key + 1, 0, gitHubUserModels.size());
                int lastItem = inRange(firstItem + pageSize, 0, gitHubUserModels.size());

                List<GitHubUserModel> gitHubUserModelsToPass;

                if (firstItem == lastItem) {

                    gitHubUserModelsToPass = new ArrayList<>();

                } else {

                    gitHubUserModelsToPass = gitHubUserModels.subList(firstItem, lastItem);
                }
                callback.onResult(gitHubUserModelsToPass);
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onComplete() {

            }
        });
    }

    @Override
    public void loadBefore(@NonNull final LoadParams<Integer> params, @NonNull final LoadCallback<GitHubUserModel> callback) {

        mApiEndPoints.getGitHubUsers().subscribe(new Observer<List<GitHubUserModel>>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(List<GitHubUserModel> gitHubUserModels) {

                int pageSize = Math.min(20, params.requestedLoadSize);
                int lastItem = inRange(params.key - 1, 0, gitHubUserModels.size());
                int firstItem = inRange(lastItem - pageSize, 0, gitHubUserModels.size());

                List<GitHubUserModel> gitHubUserModelsToPass;

                if (firstItem == lastItem) {

                    gitHubUserModelsToPass = new ArrayList<>();

                } else {

                    gitHubUserModelsToPass = gitHubUserModels.subList(firstItem, lastItem);
                }
                callback.onResult(gitHubUserModelsToPass);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }
}

Logcat

Process: com.happyemi.paginglibdemo, PID: 8464
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.happyemi.paginglibdemo.GitHubUserModel.getId()' on a null object reference
    at com.happyemi.paginglibdemo.GitHubUserAdapter.onBindViewHolder(GitHubUserAdapter.java:37)
    at com.happyemi.paginglibdemo.GitHubUserAdapter.onBindViewHolder(GitHubUserAdapter.java:14)
    at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6673)
    at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6714)
    at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5647)
    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5913)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5752)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5748)
    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2232)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1559)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1519)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:614)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3812)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3529)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:4082)
    at android.view.View.layout(View.java:16969)
    at android.view.ViewGroup.layout(ViewGroup.java:5583)
    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1189)
    at android.view.View.layout(View.java:16969)
    at android.view.ViewGroup.layout(ViewGroup.java:5583)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
    at android.view.View.layout(View.java:16969)
    at android.view.ViewGroup.layout(ViewGroup.java:5583)
    at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:443)
    at android.view.View.layout(View.java:16969)
    at android.view.ViewGroup.layout(ViewGroup.java:5583)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
    at android.view.View.layout(View.java:16969)
    at android.view.ViewGroup.layout(ViewGroup.java:5583)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:2001)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1844)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1753)
    at android.view.View.layout(View.java:16969)
    at android.view.ViewGroup.layout(ViewGroup.java:5583)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
    at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2728)
    at android.view.View.layout(View.java:16969)
    at android.view.ViewGroup.layout(ViewGroup.java:5583)
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2552)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2255)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1321)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6708)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:894)
    at android.view.Choreographer.doCallbacks(Choreographer.java:696)
    at android.view.Choreographer.doFrame(Choreographer.java:631)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:880)
    at android.os.Handler.handleCallback(Handler.java:822)
    at android.os.Handler.dispatchMessage(Handler.java:104)
    at android.os.Looper.loop(Looper.java:207)
    at android.app.ActivityThread.main(ActivityThread.java:5811)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$

I have tried with all three DataSource classes (PageKeyedDataSource, ItemKeyedDataSource, PositionalDataSource) but not getting what I'm missing.

Any help will be appreciated.


回答1:


Actually you forgot to post the value inside DataSource.Factory().

Inside GitHubUserViewModel.java class change your DataSource.Factory method code to :

DataSource.Factory<Integer, GitHubUserModel> dataSourceFactory = new DataSource.Factory<Integer, GitHubUserModel>() {
            @Override
            public DataSource<Integer, GitHubUserModel> create() {
                GitHubUserDataSource gitHubUserDataSource = new GitHubUserDataSource(mApiEndPoints);
                mGitHubLiveData.postValue(gitHubUserDataSource); // add this line.
                return gitHubUserDataSource;
            }
        };

Read more about postValue() method here - MutableLiveData.



来源:https://stackoverflow.com/questions/51999197/android-paging-library-which-datasource-i-should-use

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!