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