0

I'm trying to implement pagination in recyclerview. Following are my java classes:

MyAdapter.java

    package com.example.opinion;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

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


/**
 * Created by manish on 7/18/2016.
 */
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private ArrayList<String> movieName = new ArrayList();


    public MyAdapter(ArrayList film)
    {
        this.movieName = film;
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_items, null);
        // set the view's size, margins, paddings and layout parameters
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        holder.movieText.setText(movieName.get(position));



    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount()
    {
        System.out.print(movieName.size());
        return movieName.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView movieText;

        public ViewHolder(View v) {
            super(v);
            movieText = (TextView) v.findViewById(R.id.movieName);
        }
    }

}

viewfragment.java : here i'm fetching the data on my local network. In this file the loadMore(current_page) function only fetches 3 values at time. The first time when it is called, those three values are only visible in the cardview inside recyclerview. I don't know where the problem is!

package com.example.opinion;



import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Text;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.content.Intent;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Path;


public class ViewFragment extends Fragment {

    private static final String PREFS_NAME = "Prefname";



    public int j =0;
    static String quesText;


    //public static final String BASE_URL = "http://192.168.0.104/";

    public interface PostquesApi{
        @GET("ques/{i}")
        Call<quesGetResponse> quesget(@Path("i") String i);
    }

    static class quesGetResponse {

        String ques1;
        String ques2;
        String ques3;
        String quid1;
        String quid2;
        String quid3;

        public quesGetResponse(String ques1, String ques2, String ques3, String u1, String u2,String u3){
            this.ques1 = ques1;
            this.ques2 = ques2;
            this.ques3 = ques3;
            this.quid1 = u1;
            this.quid2 = u2;
            this.quid3 = u3;
            }
    }
    //View rootView;
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;

    private ArrayList movieList = new ArrayList();
    private static int current_page = 1;




    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        final View rootView = inflater.inflate(R.layout.fragment_view, container, false);

        for(int k=0; k<2; k++) {
            loadData(current_page);
        }
        System.out.println("contents of movie list: "+ movieList);

        mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        LinearLayoutManager feedLayoutManager = new LinearLayoutManager(getActivity());
        mAdapter = new MyAdapter(movieList);
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(feedLayoutManager);

        // specify an adapter (see also next example)

        mRecyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(
                feedLayoutManager) {
            @Override
            public void onLoadMore(int current_page) {
                // do somthing...

                loadMoreData(current_page);

            }

        });

        /*qt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent comm = new Intent(getActivity(), Comments.class);
                quesText = qt2.getText().toString();

                //comm.putExtra(quesText, Text );
                startActivity(comm);
            }
        });
        qt3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent comm = new Intent(getActivity(), Comments.class);
                quesText = qt3.getText().toString();

                //comm.putExtra(quesText, Text );
                startActivity(comm);
            }
        });*/

        return rootView;

    }
    public void loadData(int page) {
        // Send an API request to retrieve appropriate data using the offset value as a parameter.
        //  --> Deserialize API response and then construct new objects to append to the adapter
        //  --> Notify the adapter of the changes
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Login.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        PostquesApi apiService = retrofit.create(PostquesApi.class);
        Call<quesGetResponse> call = apiService.quesget(Integer.toString(j));
        call.enqueue(new Callback<quesGetResponse>() {
            @Override
            public void onResponse(Call<quesGetResponse> call, Response<quesGetResponse> response) {
                quesGetResponse decodedResponse = response.body();
                if (decodedResponse != null) {
                    if (decodedResponse.ques1 != null && decodedResponse.quid1.compareTo(Login.user_id) != 0)
                    {
                        movieList.add(decodedResponse.ques1);
                    }
                    if (decodedResponse.ques2 != null && decodedResponse.quid2.compareTo(Login.user_id) != 0)
                    {
                        movieList.add(decodedResponse.ques2);
                    }
                    if (decodedResponse.ques3 != null && decodedResponse.quid3.compareTo(Login.user_id) != 0)
                    {
                        movieList.add(decodedResponse.ques3);
                    }
                }

                if (decodedResponse.ques1 == null || decodedResponse.ques2 == null || decodedResponse.ques3 == null) {
                    Context context = getActivity().getApplicationContext();
                    CharSequence text = "Sorry!! no more questions in the database...";
                    int duration = Toast.LENGTH_SHORT;

                    Toast toast = Toast.makeText(context, text, duration);
                    toast.show();
                }

                j = j + 3;
            }

            @Override
            public void onFailure(Call<quesGetResponse> call, Throwable t) {

            }
        });
    }
    private void loadMoreData(int current_page) {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Login.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        PostquesApi apiService = retrofit.create(PostquesApi.class);
        Call<quesGetResponse> call = apiService.quesget(Integer.toString(j));
        call.enqueue(new Callback<quesGetResponse>() {
            @Override
            public void onResponse(Call<quesGetResponse> call, Response<quesGetResponse> response) {
                quesGetResponse decodedResponse = response.body();
                if (decodedResponse != null) {
                    if (decodedResponse.ques1 != null && decodedResponse.quid1.compareTo(Login.user_id) != 0)
                    {
                        movieList.add(decodedResponse.ques1);
                    }
                    if (decodedResponse.ques2 != null && decodedResponse.quid2.compareTo(Login.user_id) != 0)
                    {
                        movieList.add(decodedResponse.ques2);
                    }
                    if (decodedResponse.ques3 != null && decodedResponse.quid3.compareTo(Login.user_id) != 0)
                    {
                        movieList.add(decodedResponse.ques3);
                    }
                }

                if (decodedResponse.ques1 == null || decodedResponse.ques2 == null || decodedResponse.ques3 == null) {
                    Context context = getActivity().getApplicationContext();
                    CharSequence text = "Sorry!! no more questions in the database...";
                    int duration = Toast.LENGTH_SHORT;

                    Toast toast = Toast.makeText(context, text, duration);
                    toast.show();
                }

                j = j + 3;
            }

            @Override
            public void onFailure(Call<quesGetResponse> call, Throwable t) {

            }
        });



        mAdapter.notifyDataSetChanged();

    }

}

EndlessRecyclerOnScrollListener.java: The file that implements the logic for pagination.

package com.example.opinion;

import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

/**
 * Created by manish on 7/20/2016.
 */

public abstract class EndlessRecyclerOnScrollListener extends
        RecyclerView.OnScrollListener {
    public static String TAG = EndlessRecyclerOnScrollListener.class
            .getSimpleName();

    private int previousTotal = 0;
    private boolean loading = true;
    private int visibleThreshold = 3;
    int firstVisibleItem, visibleItemCount, totalItemCount;

    private int current_page = 1;

    private LinearLayoutManager mLinearLayoutManager;

    public EndlessRecyclerOnScrollListener(
            LinearLayoutManager linearLayoutManager) {
        this.mLinearLayoutManager = linearLayoutManager;
    }

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

        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = mLinearLayoutManager.getItemCount();
        firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading
                && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
            // End has been reached

            // Do something
            current_page++;

            onLoadMore(current_page);

            loading = true;
        }
    }

    public abstract void onLoadMore(int current_page);
}

If someone can review it and tell me the corrections needed in the above files or can direct me to some resource, it will be really appreciated.

Chintan Desai
  • 2,607
  • 2
  • 22
  • 25
manish kumar
  • 53
  • 1
  • 1
  • 9

1 Answers1

2

I would suggest instead of using EndlessRecyclerOnScrollListener class and listening to the Recyclerview's scroll event you should watch inside MyAdapter class.

1. First add one interface

public interface GetNewDataEvents {
        void getNewAdapterData();
    }

2. Initialize that interface in MyAdapter class from where you are adding your data by implementing it.

3. you can easily find which item is being loading currently in bindViewHolder using

if(position==(movieName.size()-1)

and in it you can easily call that interface method and load new data in it.

This thing denotes that second last item is being currently loading and you should add new data if any.

If you get new data you can easily load it into your adapter and call notifyItemRangeChanged with it to get performance and implementing best practices by not loading whole adapter with only few items changed.

if you want to take reference for it you can go here

Community
  • 1
  • 1
Chintan Desai
  • 2,607
  • 2
  • 22
  • 25