Its the first time I am using onscroll listener. My problem is how to fetch 20 new rows every time I scroll down ?.
I understand when I scroll down the grid view this code will be executed.
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
this.currentFirstVisibleItem = firstVisibleItem;
this.currentVisibleItemCount = visibleItemCount;
this.totalItem = totalItemCount;
if ((totalItemCount - visibleItemCount) <= (firstVisibleItem + 20)) {
// the below when executed will get all the rows ,I only need 20 rows
handler.execute().get();
}
}
this is my code
// the load more in the grid view, fetch new images.
mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
private int currentVisibleItemCount;
private int currentScrollState;
private int currentFirstVisibleItem;
private int totalItem;
private LinearLayout lBelow;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
this.currentScrollState = scrollState;
this.isScrollCompleted();
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
this.currentFirstVisibleItem = firstVisibleItem;
this.currentVisibleItemCount = visibleItemCount;
this.totalItem = totalItemCount;
if ((totalItemCount - visibleItemCount) <= (firstVisibleItem + 20)) {
// load new 20 row but how to do that
}
}
private void isScrollCompleted() {
if (totalItem - currentFirstVisibleItem == currentVisibleItemCount
&& this.currentScrollState == SCROLL_STATE_IDLE) {
Log.d("a", "poooppii");
}
}
;
});
this is where the connection happens
protected void showList(){
try {
JSONObject jsonObj = new JSONObject(myJSON);
peoples = jsonObj.getJSONArray("result");
System.out.println("Length:"+peoples.length());
int J_length=peoples.length()-1;
jsonObj= peoples.getJSONObject(J_length);
Listitem = new ArrayList<Listitem>();
for (int i = 0; i < peoples.length(); i++) {
JSONObject c = peoples.getJSONObject(i);
String id = c.getString("id");
String url = c.getString("url");
int intid = 0;
try {
intid = Integer.parseInt(id.toString());
} catch (NumberFormatException nfe) {
System.out.println("Could not parse " + nfe);
}
Listitem.add(new Listitem(id, url));
System.out.println(Listitem);
}
//}
if (mListener != null)
mListener.myMethod(Listitem);
} catch (JSONException e) {
e.printStackTrace();
}
}
You need to maintain base
and limit
for data load. Initialize your base and limit variable.
int base = 0, limit = 20;
Increase your base
variable whenever loading new items.
base = base + limit;
handler.execute().get();
Pass base
and limit
variable in your API
call, so that you can use it in query from API
side.
Note : base is a value from which position you need to start fetching values. limit is a value for how many rows you need to fetch.
Refer this for limit query in sqlite.
Refer this for limit query in MySql.
Refer this for limit query in SQL.
Here is an working code, Kindly modify as per your use -
Let assume following is your model -
public class MyModel {
String name;
}
You need one interface -
public interface PagingListener<T> {
void onItemUpdate(ArrayList<T> allData);
}
Design your adapter like this -
public class CouponsAdapter extends RecyclerView.Adapter<CouponsAdapter.CouponHolder> implements View.OnClickListener, PagingListener<MyModel> {
private final static int TYPE_LOADING = 0;
private final static int TYPE_DATA = 1;
private FragmentActivity activity;
private LayoutInflater inflater;
private PagingRequestHandler<MyModel> pagingRequestHandler;
private ArrayList<MyModel> data = null;
public CouponsAdapter(FragmentActivity activity) {
this.activity = activity;
inflater = LayoutInflater.from(activity);
this.data = new ArrayList<>();
this.pagingRequestHandler = new PagingRequestHandler<>(data, this);
}
@Override
public int getItemViewType(int position) {
return position >= data.size() ? TYPE_LOADING : TYPE_DATA;
}
@Override
public CouponHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == TYPE_DATA) {
view = inflater.inflate(R.layout.item_coupons_card_block, parent, false);
} else {
view = inflater.inflate(R.layout.item_drawer_payment_loading, parent, false);
}
return new CouponHolder(view, viewType);
}
@Override
public void onBindViewHolder(CouponHolder holder, int position) {
if (getItemViewType(position) == TYPE_DATA) {
//Bind your view here
}
pagingRequestHandler.checkAndMakeRequestForMoreData(position); //Will check and make request
}
@Override
public int getItemCount() {
return data.size() + (pagingRequestHandler.isNoMoreDataLeft() ? 0 : 1); // If no data then it will return 1 to show loading
}
@Override
public void onClick(View v) {
}
@Override
public void onItemUpdate(ArrayList<MyModel> allData) {
this.data = allData; // will update data with updated content
notifyDataSetChanged();
}
public class CouponHolder extends RecyclerView.ViewHolder {
public CouponHolder(View itemView, int itemType) {
super(itemView);
if (itemType == TYPE_DATA) {
}
}
}
}
And now this is the paging request handler, that will keep track on page number and will make request for next page -
public class PagingRequestHandler<T> {
public static final int PAGE_SIZE = 10;
private final PagingListener listener;
private final ArrayList<MyModel> arrayList;
private final String url = "Your Url here";
private boolean noMoreDataLeft;
private int pagingIndex = 0;
private boolean requestGoingOn;
public PagingRequestHandler(ArrayList<MyModel> data, PagingListener<MyModel> listener) {
this.listener = listener;
this.arrayList = data;
fetchMoreData();
}
private void fetchMoreData() {
requestGoingOn = true;
Call<MyModel[]> getCoupons = Utils.getRetrofit().getCoupons(url + "/" + pagingIndex); // I am using retrofit for network call, you can use your own
getCoupons.enqueue(new Callback<MyModel[]>() {
@Override
public void onResponse(Response<MyModel[]> response, Retrofit retrofit) {
try {
requestGoingOn = false;
MyModel[] couponModelDses = response.body();
if (couponModelDses != null) {
for (MyModel couponModelDse : couponModelDses) {
arrayList.add(couponModelDse);
}
if (couponModelDses.length < PAGE_SIZE)
noMoreDataLeft = true;
listener.onItemUpdate(arrayList);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Throwable t) {
requestGoingOn = false;
}
});
}
public boolean isNoMoreDataLeft() {
return noMoreDataLeft;
}
public void checkAndMakeRequestForMoreData(int position) {
if (!noMoreDataLeft && !requestGoingOn && position > (PAGE_SIZE * pagingIndex)) {
if ((position % PAGE_SIZE) > (int) (PAGE_SIZE * .7)) {
pagingIndex++;
fetchMoreData();
}
}
}
}
How it works - The adapter is initialising the Handler, which make network call for first time. The adapter now calls handler api to check if 70% of page is scrolled on every onBind. Now if 70% of data has been shown then it makes network call againe and makes a variable called requestGoingOn true, so you can show a loader in list. Wher request completed the handler is adding data to the arraylist and updating adapter by calling the callback onItemUpdate
.
Hope it will help, please let me know if you need further assistance :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With