javaandroidandroid-paging-library

Why does the paging library stop loading data after several calls?


I implemented a paging library and it does not work quite as it should. I request data from the github and paginate the list of repositories. The code works well, but after several changes to the search query, it stops loading data. In the debug, the data always loads well. I guess the problem is asynchrony, but I can’t figure out where to look. My code:

RepoDataSource

public class RepoDataSource extends PageKeyedDataSource<Integer, Repo> {
@Override
    public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, Repo> callback) {
        Timber.d("Initial RepoDataSource");
        try {
            Response<RepoSearchResponse> response = githubService.searchRepos(query, firstNumberPage).execute();
            RepoSearchResponse repoSearchResponse = response.body();
            if (repoSearchResponse != null) {
                List<Repo> items = repoSearchResponse.getItems();
                callback.onResult(items, 1, 2);
            }
        } catch (IOException e) {
            Timber.i(e);
        }
    }

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

    @Override
    public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Repo> callback) {
        Timber.d("Fetching next page: %s", params.key);
        try {
            Response<RepoSearchResponse> response = githubService.searchRepos(query, params.key).execute();
            if (response.isSuccessful()) {
                RepoSearchResponse repoSearchResponse = response.body();
                if (repoSearchResponse != null) {
                    List<Repo> items = repoSearchResponse.getItems();
                    callback.onResult(items, params.key + 1);
                }
            }
        } catch (IOException e) {
            Timber.i(e);
        }
    }
}

GithubApiCall

@GET("search/repositories")
    Call<RepoSearchResponse> searchRepos(@Query("q") String query, @Query("page") Integer page);

RepoDataSourceFactory

public class RepoDataSourceFactory extends DataSource.Factory<Integer, Repo> {

    private GithubService githubService;
    private String query;

    public RepoDataSourceFactory(GithubService githubService, String query) {
        this.githubService = githubService;
        this.query = query;
    }

    @NonNull
    @Override
    public DataSource<Integer, Repo> create() {
        return new RepoDataSource(githubService, query);
    }
}

Repository method

public class RepoRepository {
...
...
public RepoDataSourceFactory getRepoPagedFactory(String query) {
        return new RepoDataSourceFactory(githubService, query);
    }
}

ViewModel

public final class MyViewModel {
...
public MutableLiveData<String> searchQuery = new MutableLiveData<>();
...
public LiveData<PagedList<Repo>> getRepos() {
        return Transformations.switchMap(searchQuery, query -> {
            RepoDataSourceFactory factory = repository.getRepoPagedFactory(query);
            return new LivePagedListBuilder<>(factory, pagedListConfig).build();
        });
    }
...
public SearchView.OnQueryTextListener listener = new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            if (query != null && !query.trim().equals("")) {
                searchQuery.postValue(query);
            }
            return true;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            return true;
        }
    };
...
}

And in my activity

viewModel.getRepos().observe(this, adapter::submitList);

Solution

  • There is nothing wrong with your code. I was on a GitHub project, and was stuck in the same problem until I realize GitHub has a Rate Limit of 10 requests per minute for unauthenticated requests. But if it is an authenticated one, you can make up to 30 requests per minute.

    I assume you also send request for every changes in the search query, just like I did, where typing/changing 5 characters equals 5 requests. So the real cause is the very limited request rate from GitHub, not your code.

    Check this out: https://developer.github.com/v3/search/#rate-limit