Tatson Baptista Tatson Baptista - 2 months ago 56
Android Question

How to implement load more recyclerview in android

I want to implement load more in Recyclerview. Here is the code.
The code is from github. https://gist.github.com/ssinss/e06f12ef66c51252563e

MainActivity code:

package com.example.tatson.bila;
import android.app.ProgressDialog;
import android.os.AsyncTask;

import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import com.example.tatson.bila.CardAdapter;
import com.example.tatson.bila.Config;
import com.example.tatson.bila.SuperHeroes;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Text;

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


public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener{

SwipeRefreshLayout swipeLayout;

LinearLayoutManager mLayoutManager;

// initially offset will be 0, later will be updated while parsing the json
private int offSet = 0;

private int previousTotal = 0;


int pastVisiblesItems, visibleItemCount, totalItemCount;
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem;
private int current_page = 1;
//Creating a List of superheroes
private List<SuperHeroes> listSuperHeroes;

//Creating Views
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
public String Img;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);

//Initializing our superheroes list
listSuperHeroes = new ArrayList<>();


mLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLayoutManager);

swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);

swipeLayout.post(new Runnable() {
@Override
public void run() {
swipeLayout.setRefreshing(true);

getData();
}
}
);

recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(linearLayoutManager) {
@Override
public void onLoadMore(int current_page) {

Log.d("End","Sucess");

}
});

}


//This method will get data from the web api
private void getData(){
//Showing a progress dialog
// final ProgressDialog loading = ProgressDialog.show(this,"Loading Data", "Please wait...",false,false);

// appending offset to url
String url = Config.DATA_URL;
String url1 = url + offSet;
//Creating a json array request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url1,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
//Dismissing progress dialog
// loading.dismiss();

//calling method to parse json array
parseData(response);
adapter.notifyDataSetChanged();
// stopping swipe refresh
swipeLayout.setRefreshing(false);
}

},

new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {

}
});



//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);

//Adding request to the queue
requestQueue.add(jsonArrayRequest);


}

//This method will parse json data
private void parseData(JSONArray array){
for(int i = 0; i<array.length(); i++) {
SuperHeroes superHero = new SuperHeroes();
CardAdapter car = new CardAdapter();
JSONObject json = null;
try {
json = array.getJSONObject(i);
superHero.setImageUrl(json.getString(Config.TAG_IMAGE_URL));
Img =json.getString(Config.TAG_IMAGE_URL);
superHero.setName(json.getString(Config.TAG_NAME));
superHero.setRank(json.getInt(Config.TAG_RANK));
// superHero.setRealName(json.getString(Config.TAG_REAL_NAME));
//superHero.setCreatedBy(json.getString(Config.TAG_CREATED_BY));
//superHero.setFirstAppearance(json.getString(Config.TAG_FIRST_APPEARANCE));
int rank = json.getInt("pid");

// updating offset value to highest value
if (rank >= offSet)
offSet = rank;

// ArrayList<String> powers = new ArrayList<String>();

//JSONArray jsonArray = json.getJSONArray(Config.TAG_POWERS);

/* for(int j = 0; j<jsonArray.length(); j++){
powers.add(((String) jsonArray.get(j))+"\n");
}*/
//superHero.setPowers(powers);
Log.d("test",Img);
car.setImageUrl(Img);


} catch (JSONException e) {
e.printStackTrace();
}
listSuperHeroes.add(superHero);

}

//Finally initializing our adapter
adapter = new CardAdapter(listSuperHeroes, this);

//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);

}


@Override
public void onRefresh() {
listSuperHeroes.clear();

refreshItems();
}
void refreshItems() {
// Load items
getData();

// Load complete
onItemsLoadComplete();
}
void onItemsLoadComplete() {
// Update the adapter and notify data set changed
adapter.notifyDataSetChanged();
//Finally initializing our adapter
adapter = new CardAdapter(listSuperHeroes, this);

//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);

// Stop refresh animation

}
}


EndlessRecyclerOnScrollListener class code:

package com.example.tatson.bila;

/**
* Created by Tatson on 23-11-2015.
*/
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

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

private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
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 ) {
// End has been reached

// Do something
current_page++;
Log.d("End", "Sucess");

onLoadMore(current_page);

loading = true;
}
}

public abstract void onLoadMore(int current_page);
}


Thank you.

Answer

I found an answer here that, I believe, is much better than most I've seen on SO and elsewhere.

The idea is simple: in onScrolled in your RecyclerView's ScrollListener, check if the last completely visible item is the last item in your data set.

        if(llm.findLastCompletelyVisibleItemPosition() == data.length() -1){
            //bottom of list!
            loadMoreData();
        }

This happens with a method in the LinearLayoutManager. Calling LinearLayoutManager#findLastCompletelyVisibleItemPosition() can comparing it to the position of the last item in your dataset let's you know when you can load more.

I haven't tried this for the GridLayoutManager.

UPDATE

LinearLayoutManager#findLastVisibleItemPosition() is a better alternative to LinearLayoutManager#findLastCompletelyVisibleItemPosition(), especially when your items are longer than the window height.

Comments