I am using blogger API, retrofit, and MVVM in my app, I trying to use pagination to load more posts when user is scrolling, the problem happening here the response is loading it self "the same list / same ten posts is loading again"
here's my code
PostsClient Class
public class PostsClient {
private static final String TAG = "PostsClient";
private static final String KEY = "XYZ sensitive key!";
private static final String BASE_URL = "https://www.googleapis.com/blogger/v3/blogs/4294497614198718393/";
private PostInterface postInterface;
private static PostsClient INSTANCE;
public PostsClient() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
postInterface = retrofit.create(PostInterface.class);
}
public static PostsClient getINSTANCE() {
if(INSTANCE == null){
INSTANCE = new PostsClient();
}
return INSTANCE;
}
public Call<PostList> getPostList(){
return postInterface.getPostList(KEY);
}
}
[PostViewModel]
public class PostViewModel extends ViewModel {
public static final String TAG = "PostViewModel";
public MutableLiveData<PostList> postListMutableLiveData = new MutableLiveData<>();
public MutableLiveData<PostList> postListByLabelMutableLiveData = new MutableLiveData<>();
public MutableLiveData<String> finalURL = new MutableLiveData<>();
public MutableLiveData<String> token = new MutableLiveData<>();
public void getPosts(){
if (token.getValue() != "") {
finalURL.setValue(finalURL.getValue() + "&pageToken=" + token.getValue());
}
if (token == null) {
return;
}
PostsClient.getINSTANCE().getPostList().enqueue(new Callback<PostList>() {
@Override
public void onResponse(@NotNull Call<PostList> call, @NotNull Response<PostList> response) {
PostList list = response.body();
if (list.getItems() != null) {
token.setValue(list.getNextPageToken());
postListMutableLiveData.setValue(list);
}
Log.i(TAG,response.body().getItems().toString());
}
@Override
public void onFailure(Call<PostList> call, Throwable t) {
Log.e(TAG,t.getMessage());
}
});
}
public void getPostListByLabel(){
PostsByLabelClient.getINSTANCE().getPostListByLabel(finalURL.getValue()).enqueue(new Callback<PostList>() {
@Override
public void onResponse(Call<PostList> call, Response<PostList> response) {
postListByLabelMutableLiveData.setValue(response.body());
}
@Override
public void onFailure(Call<PostList> call, Throwable t) {
}
});
}
}
HomeFragment Class "The main page"
public class HomeFragment extends Fragment {
private PostViewModel postViewModel;
public static final String TAG = "HomeFragment";
private RecyclerView recyclerView;
private PostAdapter postAdapter;
private List<Item> itemArrayList;
private boolean isScrolling = false;
private int currentItems, totalItems, scrollOutItems, selectedIndex;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
postViewModel = new ViewModelProvider(this).get(PostViewModel.class);
postViewModel.getPosts();
View root = inflater.inflate(R.layout.fragment_home, container, false);
itemArrayList = new ArrayList<>();
recyclerView = root.findViewById(R.id.homeRecyclerView);
postAdapter = new PostAdapter(getContext(),itemArrayList);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext()
, linearLayoutManager.getOrientation());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setAdapter(postAdapter);
// textView.setText(s);
postViewModel.postListMutableLiveData.observe(HomeFragment.this, new Observer<PostList>() {
@Override
public void onChanged(PostList postList) {
itemArrayList.addAll(postList.getItems());
postAdapter.notifyDataSetChanged();
}
});
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
isScrolling = true;
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
currentItems = linearLayoutManager.getChildCount();
totalItems = linearLayoutManager.getItemCount();
scrollOutItems = linearLayoutManager.findFirstVisibleItemPosition();
if (isScrolling && (currentItems + scrollOutItems == totalItems)) {
isScrolling = false;
postViewModel.getPosts();
postAdapter.notifyDataSetChanged();
}
}
}
});
return root;
}
}
’More explanation
on PostViewModel I created one variable
public MutableLiveData<String> token = new MutableLiveData<>();
This token that represents a new page/response will carry "each page has a list / ten new posts"
on HomeFragment
I created three integer values
private int currentItems, totalItems, scrollOutItems, selectedIndex;
and one boolean
private boolean isScrolling = false;
then I used recyclerView.addOnScrollListener
with this way to load the next ten posts, but it's not working like I said before, its loading the same result/list
The result on imgur.comAfter hundreds of tries, I finally solved it, here's the solution of problem
Firstly I changed the GET
method in the API PostInterface
and make it take @URL
instead of @Query
KEY like this
public interface PostInterface {
@GET
Call<PostList> getPostList(@Url String URL);
}
Secondary I edited the PostsClient
removed final from BASE_URL
private static String BASE_URL
and create a setter & getter for BASE URL & KEY
public static String getKEY() {
return KEY;
}
public static String getBaseUrl() {
return BASE_URL;
}
Thirdly & finally I moved this if statement for the token checker after the response
public void getPosts(){
Log.e(TAG,finalURL.getValue());
PostsClient.getINSTANCE().getPostList(finalURL.getValue()).enqueue(new Callback<PostList>() {
@Override
public void onResponse(@NotNull Call<PostList> call, @NotNull Response<PostList> response) {
PostList list = response.body();
if (list.getItems() != null) {
Log.e(TAG,list.getNextPageToken());
token.setValue(list.getNextPageToken());
postListMutableLiveData.setValue(list);
}
if (token.getValue() == null || !token.getValue().equals("") ) {
finalURL.setValue(finalURL.getValue() + "&pageToken=" + token.getValue());
}
// Log.i(TAG,response.body().getItems().toString());
}
@Override
public void onFailure(Call<PostList> call, Throwable t) {
Log.e(TAG,t.getMessage());
}
});
}