user3662974 user3662974 - 2 months ago 25
Android Question

how to edit? infinite recycleview

i'm making infinite recycleview with json.

this code works only half

i can see items loaded at first time.

but when i scroll down,

nothing happen,
i guess, maybe onLoadMore() is not working.

i been edited 4hours

direct me

where should i edit?

thank you for interest in this.

MainActivity

package com.androidcss.jsonexample;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
private RecyclerView mRVFishPrice;
private AdapterFish mAdapter;
protected Handler handler;
List<DataFish> data=new ArrayList<>();

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


//Make call to AsyncTask
new AsyncLogin().execute();


handler = new Handler();

mRVFishPrice = (RecyclerView)findViewById(R.id.fishPriceList);
mAdapter = new AdapterFish(MainActivity.this, data, mRVFishPrice);
mRVFishPrice.setAdapter(mAdapter);
mRVFishPrice.setLayoutManager(new LinearLayoutManager(MainActivity.this));

mAdapter.setOnLoadMoreListener(new AdapterFish.OnLoadMoreListener() {

@Override
public void onLoadMore() {

//add progress item
data.add(null);
mAdapter.notifyItemInserted(data.size() - 1);

handler.postDelayed(new Runnable() {

@Override
public void run() {

new AsyncLogin().execute();

}

}, 2000);

System.out.println("load");
}

});

}

private class AsyncLogin extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(MainActivity.this);
HttpURLConnection conn;
URL url = null;

@Override
protected void onPreExecute() {
super.onPreExecute();

//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.setCancelable(false);
pdLoading.show();

}

@Override
protected String doInBackground(String... params) {
try {

// Enter URL address where your json file resides
// Even you can make call to php file which returns json data
url = new URL("http://10.0.2.2/test/example.json");

} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {

// Setup HttpURLConnection class to send and receive data from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");

// setDoOutput to true as we recieve data from json file
conn.setDoOutput(true);

} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}

try {

int response_code = conn.getResponseCode();

// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {

// Read data sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;

while ((line = reader.readLine()) != null) {
result.append(line);
}

// Pass data to onPostExecute method
return (result.toString());

} else {

return ("unsuccessful");
}

} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}


}

@Override
protected void onPostExecute(String result) {

//this method will be running on UI thread

pdLoading.dismiss();
List<DataFish> data=new ArrayList<>();

pdLoading.dismiss();
try {

JSONArray jArray = new JSONArray(result);

// Extract data from json and store into ArrayList as class objects
for(int i=0;i<jArray.length();i++){
JSONObject json_data = jArray.getJSONObject(i);
DataFish fishData = new DataFish();
fishData.fishImage= json_data.getString("fish_img");
fishData.fishName= json_data.getString("fish_name");
fishData.catName= json_data.getString("cat_name");
fishData.sizeName= json_data.getString("size_name");
fishData.price= json_data.getInt("price");
data.add(fishData);
}

// Setup and Handover data to recyclerview
mRVFishPrice = (RecyclerView)findViewById(R.id.fishPriceList);
mAdapter = new AdapterFish(MainActivity.this, data, mRVFishPrice);
mRVFishPrice.setAdapter(mAdapter);
mRVFishPrice.setLayoutManager(new LinearLayoutManager(MainActivity.this));

} catch (JSONException e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}

}

}
}


AdapterFish.java

package com.androidcss.jsonexample;

import android.content.Context;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import java.util.Collections;
import java.util.List;

public class AdapterFish extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private Context context;
final private Context context2 = context;
private LayoutInflater inflater;
List<DataFish> data= Collections.emptyList();
DataFish current;
int currentPos=0;



private final int VIEW_ITEM = 1;
private final int VIEW_PROG = 0;


// The minimum amount of items to have below your current scroll position before loading more.
private int visibleThreshold = 2;
private int lastVisibleItem, totalItemCount;
private boolean loading;
private OnLoadMoreListener onLoadMoreListener;



// create constructor to innitilize context and data sent from MainActivity
public AdapterFish(Context context, List<DataFish> data, RecyclerView recyclerView){
this.context=context;
inflater= LayoutInflater.from(context);
this.data=data;

if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {

final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);

totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
// End has been reached
// Do something
if (onLoadMoreListener != null) {

onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
});
}
}


@Override
public int getItemViewType(int position) {
return data.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}


// Inflate the layout when viewholder created
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

MyViewHolder holder;

if (viewType == VIEW_ITEM) {

View view = inflater.inflate(R.layout.container_fish, parent, false);
holder = new MyViewHolder(view);

}
else
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
RecyclerView.ViewHolder vh = new ProgressViewHolder(v);

return vh;
}

return holder;
}

// Bind data
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

// Get current position of item in recyclerview to bind data and assign values from list
MyViewHolder myHolder= (MyViewHolder) holder;
DataFish current=data.get(position);
myHolder.textFishName.setText(current.fishName);
myHolder.textSize.setText("Size: " + current.sizeName);
myHolder.textType.setText("Category: " + current.catName);
myHolder.textPrice.setText("Rs. " + current.price + "\\Kg");
myHolder.textPrice.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));

// load image into imageview using glide
Glide.with(context).load("http://192.168.1.7/test/images/" + current.fishImage)
.placeholder(R.drawable.ic_img_error)
.error(R.drawable.ic_img_error)
.into(myHolder.ivFish);

}

public void setLoaded() {
loading = false;
}

// return total item from List
@Override
public int getItemCount() {
return data.size();
}

public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}

public interface OnLoadMoreListener {
void onLoadMore();
}

public static class ProgressViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;

public ProgressViewHolder(View v) {
super(v);
progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
}
}


class MyViewHolder extends RecyclerView.ViewHolder{

TextView textFishName;
ImageView ivFish;
TextView textSize;
TextView textType;
TextView textPrice;

// create constructor to get widget reference
public MyViewHolder(View itemView) {
super(itemView);
textFishName= (TextView) itemView.findViewById(R.id.textFishName);
ivFish= (ImageView) itemView.findViewById(R.id.ivFish);
textSize = (TextView) itemView.findViewById(R.id.textSize);
textType = (TextView) itemView.findViewById(R.id.textType);
textPrice = (TextView) itemView.findViewById(R.id.textPrice);
}

}

}

Answer

I can give my own method of loading more items. You have to create your own abstract class called ScrollRecycler which extends from RecyclerView.OnScrollListener.Here it is implemantation

public abstract class ScrollRecycler extends RecyclerView.OnScrollListener {
int page = 0;
// The current offset index of data you have loaded
int startingPageIndex = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;

RecyclerView.LayoutManager mLayoutManager;

public ScrollRecycler(LinearLayoutManager layoutManager) {
    this.mLayoutManager = layoutManager;
}

public int getLastVisibleItem(int[] lastVisibleItemPositions) {
    int maxSize = 0;
    for (int i = 0; i < lastVisibleItemPositions.length; i++) {
        if (i == 0) {
            maxSize = lastVisibleItemPositions[i];
        }
        else if (lastVisibleItemPositions[i] > maxSize) {
            maxSize = lastVisibleItemPositions[i];
        }
    }
    return maxSize;
}

// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScrolled(RecyclerView view, int dx, int dy) {
    int lastVisibleItemPosition = 0;
    int totalItemCount = mLayoutManager.getItemCount();

    if (mLayoutManager instanceof StaggeredGridLayoutManager) {
        int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
        // get maximum element within the list
        lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
    } else if (mLayoutManager instanceof LinearLayoutManager) {
        lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
    }
    // If the total item count is zero and the previous isn't, assume the
    // list is invalidated and should be reset back to initial state
    if (totalItemCount < previousTotalItemCount) {
        page = startingPageIndex;
        this.previousTotalItemCount = totalItemCount;
        if (totalItemCount == 0) {
            this.loading = true;
        }
    }
    // If it’s still loading, we check to see if the dataset count has
    // changed, if so we conclude it has finished loading and update the current page
    // number and total item count.
    if (loading && (totalItemCount > previousTotalItemCount)) {
        loading = false;
        previousTotalItemCount = totalItemCount;
    }
    // If it isn’t currently loading, we check to see if we have breached
    // the visibleThreshold and need to reload more data.
    // If we do need to reload some more data, we execute onLoadMore to fetch the data.
    // threshold should reflect how many total columns there are too
    int visibleThreshold = 10;
    if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
        page++;
        onLoadMore(page);
        loading = true;
    }
}
public abstract void onLoadMore(final int page);

And you have to add your abstract class to your RecyclerView not Adapter.

public class MainActivity extends AppCompatActivity {

// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
private RecyclerView mRVFishPrice;
private AdapterFish mAdapter;
protected Handler handler;
List<DataFish> data=new ArrayList<>();

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


    //Make call to AsyncTask
    new AsyncLogin().execute();


    handler = new Handler();

    mRVFishPrice = (RecyclerView)findViewById(R.id.fishPriceList);
    mAdapter = new AdapterFish(MainActivity.this, data, mRVFishPrice);
    mRVFishPrice.setAdapter(mAdapter);
    mRVFishPrice.setLayoutManager(new LinearLayoutManager(MainActivity.this));
    mRVFishPrice.addOnScrollListener(new ScrollRecycler(new LinearLayoutManager(MainActivity.this)) {
        @Override
        public void onLoadMore(int page) {
            // you can make network call to Server in order to retrive data here page is comminh
        }
    });


}

I think it will help you