由于 ViewModel 的项目计数错误,RecyclerView 无法滚动

RecyclerView cannot be scrolled because of wrong item count from ViewModel

我正在开发一个简单的应用程序来搜索 github 用户(利用 Github API)。不幸的是,请求 return 多个项目将默认分页为 30 个项目。所以你必须在你自己的分页机制上工作。

这是我的简单逻辑:

TOTAL_PAGES = ceil(total_count/30)

if (currentPage < TOTAL_PAGES) {
    currentPage++;
    doSearchUser(who, currentPage);
}

例如你搜索用户goreng

https://api.github.com/search/users?q=goreng

它产生total_count = 33,这意味着我们的TOTAL_PAGES是2。

以及一些相关代码:

MainActivity.java

 private void doSearchUser(String who, int pageNum) {
    totalCount = viewModel.getTotalCount();
    viewModel.setSearchResult(who, pageNum);

    viewModel.getSearchResult().observe(this, new Observer<ArrayList<User>>() {
        @Override
        public void onChanged(ArrayList<User> theList) {
            searchAdapter = new SearchAdapter(context, theList);
            recyclerView.setAdapter(searchAdapter);
        }
    });

    totalCount = viewModel.getTotalCount(); // not working. always returns 0 :(
    TOTAL_PAGES = ((int)Math.ceil((double) totalCount/(double)30));
}

    private void setUpRecyclerView() {
        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        List<User> userList = new ArrayList<User>();
        searchAdapter = new SearchAdapter(context, userList) ;

        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(searchAdapter);

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

                if(!recyclerView.canScrollVertically(1) && dy != 0) {
                    if (currentPage < TOTAL_PAGES) {
                        currentPage++;
                        doSearchUser(who, currentPage);
                    }
                }
            }
        });
    }

UserViewModel.java

package com.divbyzero.app.githubusersearch.viewmodel;

import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.divbyzero.app.githubusersearch.api.APIEndPoint;
import com.divbyzero.app.githubusersearch.api.APIService;
import com.divbyzero.app.githubusersearch.response.SearchResponse;
import com.divbyzero.app.githubusersearch.model.User;

import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class UserViewModel extends ViewModel {

    private MutableLiveData<ArrayList<User>> mutableLiveData = new MutableLiveData<>();
    private int totalCount;
    private ArrayList<User> savedData = new ArrayList<User>();

    public void setSearchResult(String who, int page){
        Retrofit retrofit = APIService.getRetrofitService();
        APIEndPoint apiEndpoint = retrofit.create(APIEndPoint.class);
        Call<SearchResponse> call = apiEndpoint.getSearchResult(who, page);
        call.enqueue(new Callback<SearchResponse>() {
            @Override
            public void onResponse(Call<SearchResponse> call, Response<SearchResponse> response) {
                if (response.body() != null) {
                        savedData.addAll(response.body().getItems());
                        //mutableLiveData.setValue((ArrayList<User>) response.body().getItems());
                        mutableLiveData.setValue(savedData);
                        totalCount = response.body().getTotalCount();
                        Log.d("DBG", "OK");
                }
            }

            @Override
            public void onFailure(Call<SearchResponse> call, Throwable t) {
                Log.d("DBG", "Failed: "+t.getMessage());
            }
        });
    }

    public LiveData<ArrayList<User>> getSearchResult(){
        return mutableLiveData;
    }

    public void clear(){
        savedData.clear();
        mutableLiveData.setValue(new ArrayList<User>());
    }

    public int getTotalCount(){
        return totalCount;
    }
}

完整回购:https://github.com/anta40/GithubUserSearch

我的问题是 viewModel.getTotalCount() 最初 returns 0(而对于上面的 URL,它应该 return 33)。不过,这需要一段时间,最终会 return 33。这就是为什么我无法滚动查看更多项目。如何解决这个问题?

当你开始时你做 viewModel.setSearchResult(who, pageNum); 那是异步 api 调用。您的代码不等待结果并继续前进,然后您注册观察者。然后您尝试获取总计数,但 api 调用尚未完成。这就是你得到 0 的原因。你需要等待 api 调用完成。当你的实时数据有新项目时它就会完成,对吧?这就是为什么在方法 onChanged 中你将有 totalCount = 33

尝试这样做

viewModel.getSearchResult().observe(this, new Observer<ArrayList<User>>() {
        @Override
        public void onChanged(ArrayList<User> theList) {
            totalCount = viewModel.getTotalCount();
            TOTAL_PAGES = ((int)Math.ceil((double) totalCount/(double)30));

            searchAdapter = new SearchAdapter(context, theList);
            recyclerView.setAdapter(searchAdapter);
        }
    });