scrolllistener scrolling recyclerview more endless android json android-recyclerview infinite-scroll endlessscroll

android - more - RecyclerView Endless Infinite Scrolling Issue



recyclerview scrolllistener (8)

Intenta cambiar el

int i = start + 1; i <= end; i++

en el bucle for

int i = start + 1; i < end; i++

La validación <= agrega un elemento extra.

Estoy tratando de implementar Endless Infinite Scrolling con RecyclerView, pero solo estoy obteniendo los primeros 10 registros, no obtengo los próximos 10 registros e incluso no obtengo ningún progreso al intentar desplazarme hacia abajo.

Mientras que se suponía que obtendría los próximos 10 registros en el desplazamiento, etc. Pero obteniendo solo los primeros 10 registros

Aquí he subido una copy de mi JSON, pero no puedo recuperar datos de la misma URL, por eso estoy usando la URL del cliente y el host local.

Estoy siguiendo this tutorial

Aquí está mi código completo, ¿Puedo saber dónde estoy cometiendo un error?

JSON:

{ "names": [ { "name": "Name 1" }, { "name": "Name 2" }, .... { "name": "Name 60" } ] }

Iniciar sesión:

D/name -(13759): Name 1 D/name -(13759): Name 2 ....................... D/name -(13759): Name 60

Aquí está mi código actualizado, que estoy usando para analizar datos JSON

MainActivity.java: ACTUALIZADO

public class MainActivity extends AppCompatActivity { private Toolbar toolbar; private TextView tvEmptyView; private RecyclerView mRecyclerView; private DataAdapter mAdapter; private LinearLayoutManager mLayoutManager; private ArrayList<Student> studentList; protected Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = (Toolbar) findViewById(R.id.toolbar); tvEmptyView = (TextView) findViewById(R.id.empty_view); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); studentList = new ArrayList<Student>(); handler = new Handler(); if (toolbar != null) { setSupportActionBar(toolbar); getSupportActionBar().setTitle("Android Students"); } loadData(); } // load initial data private void loadData() { new Parser().execute("http://10.0.2.2/jsons/mytest.txt"); } class Parser extends AsyncTask<String, Void, Boolean> { ProgressDialog dialog; @Override protected void onPreExecute() { super.onPreExecute(); dialog = new ProgressDialog(MainActivity.this); dialog.show(); dialog.setCancelable(false); } @Override protected Boolean doInBackground(String... urls) { try { //------------------>> HttpGet httppost = new HttpGet(urls[0]); HttpClient httpclient = new DefaultHttpClient(); HttpResponse response = httpclient.execute(httppost); // StatusLine stat = response.getStatusLine(); int status = response.getStatusLine().getStatusCode(); if (status == 200) { HttpEntity entity = response.getEntity(); String data = EntityUtils.toString(entity); JSONObject jsono = new JSONObject(data); JSONArray jarray = jsono.getJSONArray("names"); for (int i = 0; i < jarray.length(); i++) { JSONObject object = jarray.getJSONObject(i); Student actor = new Student(); actor.setName(object.getString("name")); Log.d("name - ", object.getString("name")); studentList.add(actor); } Log.d("MainActivity:StudentList ", "The size "+studentList.size()); return true; } //------------------>> } catch (ParseException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return false; } protected void onPostExecute(Boolean result) { dialog.cancel(); Log.d("MainActivity:StudentList ", "The size "+studentList.size()); ArrayList< Student > temArray = new ArrayList< Student >(studentList.subList(0, 10)); mAdapter = new DataAdapter(temArray, mRecyclerView); Log.d("MainActivity:TempList ", "The size "+temArray.size()); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter); // 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); mLayoutManager = new LinearLayoutManager(MainActivity.this); // use a linear layout manager mRecyclerView.setLayoutManager(mLayoutManager); if (studentList.isEmpty()) { mRecyclerView.setVisibility(View.GONE); tvEmptyView.setVisibility(View.VISIBLE); } else { mRecyclerView.setVisibility(View.VISIBLE); tvEmptyView.setVisibility(View.GONE); } mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore() { //add null , so the adapter will check view_type and show progress bar at bottom studentList.add(null); mAdapter.notifyItemInserted(studentList.size() - 1); handler.postDelayed(new Runnable() { @Override public void run() { // remove progress item studentList.remove(studentList.size() - 1); mAdapter.notifyItemRemoved(studentList.size()); //add items one by one int start = studentList.size(); int end = start + 10; for (int i = start + 1; i < end; i++) { mAdapter.notifyItemInserted(studentList.size()); } mAdapter.setLoaded(); //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged(); } }, 2000); } }); } } }

DataAdapter.java:

public class DataAdapter extends RecyclerView.Adapter { private final int VIEW_ITEM = 1; private final int VIEW_PROG = 0; private List<Student> studentList; // The minimum amount of items to have below your current scroll position // before loading more. private int visibleThreshold = 5; private int lastVisibleItem, totalItemCount; private boolean loading; private OnLoadMoreListener onLoadMoreListener; public DataAdapter(List<Student> students, RecyclerView recyclerView) { studentList = students; 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 studentList.get(position) != null ? VIEW_ITEM : VIEW_PROG; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder vh; if (viewType == VIEW_ITEM) { View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.list_row, parent, false); vh = new StudentViewHolder(v); } else { View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.progress_item, parent, false); vh = new ProgressViewHolder(v); } return vh; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof StudentViewHolder) { Student singleStudent= (Student) studentList.get(position); ((StudentViewHolder) holder).tvName.setText(singleStudent.getName()); ((StudentViewHolder) holder).student= singleStudent; } else { ((ProgressViewHolder) holder).progressBar.setIndeterminate(true); } } public void setLoaded() { loading = false; } @Override public int getItemCount() { return studentList.size(); } public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) { this.onLoadMoreListener = onLoadMoreListener; } // public static class StudentViewHolder extends RecyclerView.ViewHolder { public TextView tvName; public Student student; public StudentViewHolder(View v) { super(v); tvName = (TextView) v.findViewById(R.id.tvName); v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "OnClick :" + student.getName(), Toast.LENGTH_SHORT).show(); } }); } } public static class ProgressViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public ProgressViewHolder(View v) { super(v); progressBar = (ProgressBar) v.findViewById(R.id.progressBar1); } } }

OnLoadMoreListener.java:

public interface OnLoadMoreListener { void onLoadMore(); }


Trate de NotifyItemRangeChanged

yourCurrentList.addAll(newData); mAdapter.notifyItemRangeChanged(yourCurretList.size() + 1, newDataSize);

Creo que esto te ayudará.


Tuve el mismo problema una vez que lo resuelvo usando este código ... Primero ... crea esta clase

public abstract class EndlessOnScrollListener extends OnScrollListener { public static String TAG = EndlessOnScrollListener.class.getSimpleName(); // use your LayoutManager instead private LinearLayoutManager llm; public EndlessOnScrollListener(LinearLayoutManager sglm) { this.lm = llm; } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (!recyclerView.canScrollVertically(1)) { onScrolledToEnd(); } } public abstract void onScrolledToEnd(); }

Segundo .. en tu actividad usa este

recyclerView.addOnScrollListener(new EndlessOnScrollListener() { @Override public void onScrolledToEnd() { if (!loading) { loading = true; // add 10 by 10 to tempList then notify changing in data } loading = false; } });

Esto funciona para mí ... Espero que funcione para ti.


reemplazar

private List<Student> studentList;

con

private List<Object> list;

también reemplazar

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

con

@Override public int getItemViewType(int position) { return list.get(position) instanceof Student ? VIEW_ITEM : VIEW_PROG; }

Para detectar el final de la lista puedes usar

@Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); // When went to the end of the list, load more posts if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (linearLayoutManager.findLastVisibleItemPosition() >= linearLayoutManager.getItemCount() - 1) { // Grow List } } }

También para agregar elemento de carga. añade este código en el adaptador

public void addLoadingView(){ list.add(new Object()); notifyDataSetChanged(); }


1.

Obtener los primeros 11 elementos de recyclerview en blanco (y mostrar la barra de progreso continuamente), vea la siguiente captura de pantalla:

Cambiar el método loadData como:

private void loadData() { new Parser().execute("http://clienturl.com/jsons/mytest.txt"); }

2.

Mientras que se suponía que debía obtener los primeros 10 registros, y en los próximos 10 registros, y así sucesivamente ...

Cambie el método onPostExecute de Parser como:

protected void onPostExecute(Boolean result) { dialog.cancel(); ArrayList< Student > temArray = new ArrayList< Student >(studentList.subList(0, 10)); mAdapter = new DataAdapter(temArray, mRecyclerView); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter); }

Y también elimina las siguientes líneas del método onCreate :

mAdapter = new DataAdapter(studentList, mRecyclerView); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter);


Problema 1 : ha creado una nueva instancia de mAdapter antes de configurar LayoutManager para RecyclerView. Por lo tanto, el código del constructor en el DataAdapter para agregar ScrollListener no se ejecuta ya que recyclerView.getLayoutManager() devuelve null :

if (recyclerView.getLayoutManager() instanceof LinearLayoutManager){ // code to add ScrollListener is never executed }

Solución : primero configure el LayoutManager para Recyclerview y luego cree el adaptador como se muestra a continuación:

// use a linear layout manager mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new DataAdapter(temArray, mRecyclerView); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter);

Problema 2: ha utilizado temArray para crear DataAdapter pero en onLoadMore() está utilizando la studentList de studentList para agregar / eliminar nuevos elementos, ya que la lista de studentList no está mAdapter a mAdapter sus cambios no se reflejan en la interfaz de usuario.

Solución: temArray como una variable de nivel de clase y use temArray para manipular los elementos.

//class variable private ArrayList<Student> temArray = new ArrayList<Student>(); handler.postDelayed(new Runnable() { @Override public void run() { // remove progress item temArray.remove(temArray.size() - 1); mAdapter.notifyItemRemoved(temArray.size()); //add items one by one int start = temArray.size(); int end = start + 10; if(end<=studentList.size()){ temArray.addAll(studentList.subList(start,end)); } mAdapter.setLoaded(); } }, 2000);


for (int i = start + 1; i < end; i++) { studentList.add(add data here) ; mAdapter.notifyItemInserted(studentList.size()); }


mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore() { //add null , so the adapter will check view_type and show progress bar at bottom studentList.add(null); mAdapter.notifyItemInserted(studentList.size() - 1); handler.postDelayed(new Runnable() { @Override public void run() { // remove progress item studentList.remove(studentList.size() - 1); mAdapter.notifyItemRemoved(studentList.size()); //add items one by one int start = studentList.size(); int end = start + 10; for (int i = start + 1; i < end; i++) { // studentList.add(); mAdapter.notifyItemInserted(studentList.size()); } mAdapter.setLoaded(); //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged(); } }, 2000); } });

ok, insertó la barra de progreso y luego la eliminó también, pero nunca insertó el siguiente alumno para mostrar ... algo como studentList.add ();

Espero que haya resuelto tu problema ... buena suerte ..