studio recyclerview que oncreateviewholder item imágenes ejemplo dependencia con cardview card and android android-recyclerview

android - recyclerview - oncreateviewholder que es



Inconsistencia detectada en RecyclerView, Cómo cambiar el contenido de RecyclerView mientras se desplaza (25)

Estoy usando RecyclerView para mostrar el nombre de los elementos. Mi fila contiene TextView único. Los nombres de los elementos se almacenan en List<String> mItemList .

Para cambiar el contenido de RecyclerView , reemplazo las cadenas en mItemList y llamo notifyDataSetChanged () en RecyclerViewAdapter .

Pero si trato de cambiar el contenido de mItemList mientras RecyclerView se desplaza, a veces me da java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588

Esto sucede si el tamaño de mItemList es menor que antes. Entonces, ¿cuál es la forma correcta de cambiar el contenido de RecyclerView ? ¿Es esto un error en RecyclerView ?

Aquí hay un seguimiento completo de la excepción:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258) at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265) at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093) at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956) at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725) at android.view.Choreographer.doCallbacks(Choreographer.java:555) at android.view.Choreographer.doFrame(Choreographer.java:524) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4921) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794) at dalvik.system.NativeStart.main(Native Method)

Adaptador Ver código:

private static class FileListAdapter extends RecyclerView.Adapter<FileHolder> { private final Context mContext; private final SparseBooleanArray mSelectedArray; private final List<String> mList; FileListAdapter(Context context, List<String> list, SparseBooleanArray selectedArray) { mList = list; mContext = context; mSelectedArray = selectedArray; } @Override public FileHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View view = LayoutInflater.from(viewGroup.getContext()).inflate( R.layout.file_list_item, viewGroup, false); TextView tv = (TextView) view .findViewById(R.id.file_name_text); Typeface font = Typeface.createFromAsset(viewGroup.getContext().getAssets(), viewGroup.getContext().getString(R.string.roboto_regular)); tv.setTypeface(font); return new FileHolder(view, tv); } @Override public void onBindViewHolder(FileHolder fileHolder, final int i) { String name = mList.get(i); // highlight view if selected setSelected(fileHolder.itemView, mSelectedArray.get(i)); // Set text fileHolder.mTextView.setText(name); } @Override public int getItemCount() { return mList.size(); } } private static class FileHolder extends RecyclerView.ViewHolder { public final TextView mTextView; public FileHolder(View itemView, TextView tv) { super(itemView); mTextView = tv; } }


Aunque en la respuesta aceptada se proporcionan un par de hipervínculos útiles sobre este problema, no es cierto que este comportamiento de RecyclerView durante el desplazamiento sea un error .

Si ve esta excepción, lo más probable es que se olvide de notificar al adaptador después de "cambiar" el contenido de RecyclerView . La gente llama a notifyDataSetChanged() solo después de agregar un elemento al conjunto de datos. Sin embargo, la inconsistencia ocurre no solo después de volver a llenar el adaptador, sino también cuando elimina un elemento o borra el conjunto de datos, debe actualizar la vista notificando al adaptador sobre este cambio:

public void refillAdapter(Item item) { adapter.add(item); notifyDataSetChanged(); } public void cleanUpAdapter() { adapter.clear(); notifyDataSetChanged(); /* Important */ }

En mi caso, intenté limpiar el adaptador en onStop() y rellenarlo en onStart() . Olvidé llamar a notifyDataSetChanged() después de limpiar el adaptador usando clear() . Luego, cada vez que cambiaba el estado de onStop() a onStart() y desplazaba rápidamente el RecyclerView mientras se onStart() el conjunto de datos, veía esta excepción. Si esperaba el final de la recarga sin desplazarme, no habría excepción, ya que esta vez el adaptador se puede restablecer sin problemas.

En resumen, RecyclerView no es coherente cuando está en cambio de vista. Si intenta desplazar la vista mientras se procesan los cambios en el conjunto de datos, verá java.lang.IndexOutOfBoundsException: Inconsistency detected . Para eliminar este problema, debe notificar al adaptador inmediatamente después de cambiar el conjunto de datos.


Debe usar en su recuento de getitem

public int getItemCount() { if (mList!= null) return mList.size(); else return 0; }

También actualizando la vista del reciclador, utilice esto

if (recyclerView.getAdapter() == null) { recyclerView.setHasFixedSize(true); mFileListAdapter= new FileListAdapter(this); recyclerView.setAdapter(mFileListAdapter); recyclerView.setItemAnimator(new DefaultItemAnimator()); } else { mFileListAdapter.notifyDataSetChanged(); }

Al usar esta solución no puede resolver el problema, simplemente usa una condición dentro de onBindViewHolder para resolver la excepción java.lang.IndexOutOfBoundsException

public void onBindViewHolder(FileHolder fileHolder, final int i) { if(i < mList.size) { String name = mList.get(i); setSelected(fileHolder.itemView, mSelectedArray.get(i)); fileHolder.mTextView.setText(name); } }


El problema definitivamente no se debe al desplazamiento de la vista de reciclaje, sino que está relacionado con notifyDataSetChanged () . Tenía una vista de reciclador en la que cambiaba constantemente los datos, es decir, agregar y eliminar datos. Estaba llamando a notifyDataSetChanged () cada vez que agregaba elementos a mi lista, pero no actualizaba el adaptador cada vez que se eliminaba el elemento o se borraba la lista.

Entonces para arreglar el:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 2(offset:2).state:12 at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5456)

Llamé a adapter.notifyDataSetChanged () después de list.clear () , donde fue necesario.

if (!myList.isEmpty()) { myList.clear(); myListAdapter.notifyDataSetChanged(); }

Desde entonces, nunca encontré la excepción. Espero que funcione igual para otros también. :)


En mi caso el problema era yo.

Mi configuración es un mecanismo de Recyclerview, Adapter & Cursor / Loader.

En un momento de mi aplicación, el cargador se destruye.

supportLoaderManager.destroyLoader(LOADER_ID_EVENTS)

Esperaba que Recyclerview mostrara una lista vacía ya que acabo de eliminar su fuente de datos. Lo que hace que la búsqueda de errores sea más complicada es que la lista era visible y que la conocida Excepción se produjo solo en un lanzamiento / desplazamiento / animación.

Eso me costó unas horas. :)


En mi caso, se resolvió cambiando mRecyclerView.smoothScrollToPosition(0) a

mRecyclerView.scrollToPosition(0)


Estaba enfrentando el mismo problema, java.lang.IndexOutOfBoundsException: Inconsistencia detectada .

Crear Custom LinearLayoutManager .

HPLinearLayoutManager.java

public class HPLinearLayoutManager extends LinearLayoutManager { public HPLinearLayoutManager(Context context) { super(context); } public HPLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } public HPLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * Magic here */ @Override public boolean supportsPredictiveItemAnimations() { return false; } }

crear instancia de HPLinearLayoutManager .

HPLinearLayoutManager hpLinearLayoutManager = new HPLinearLayoutManager(mContext); recyclerView.setLayoutManager(hpLinearLayoutManager);

Espero que esto te ayude.


Este problema está llegando a la vista de reciclaje si usa

adapter.setHasStableIds(true);

si lo configura, elimine esto y actualice su conjunto de datos dentro del adaptador;
si aún enfrenta el problema, invalide todas las vistas una vez que obtenga nuevos datos y luego actualice su conjunto de datos.


Estoy alterando los datos para RecyclerView en el Thread fondo. Tengo la misma Exception que el OP. Agregué esto después de cambiar los datos:

myRecyclerView.post(new Runnable() { @Override public void run() { myRecyclerAdapter.notifyDataSetChanged(); } });

Espero eso ayude


Evite notifyDatasetHasChanged () y haga lo siguiente:

public void setItems(ArrayList<Article> newArticles) { //get the current items int currentSize = articles.size(); //remove the current items articles.clear(); //add all the new items articles.addAll(newArticles); //tell the recycler view that all the old items are gone notifyItemRangeRemoved(0, currentSize); //tell the recycler view how many new items we added notifyItemRangeInserted(0, articles.size()); }


He replicado este problema. Esto sucedió cuando eliminamos elementos en el hilo de fondo de mList pero no llama a notifyDataSetChanged (). Ahora si nos desplazamos Esta excepción está llegando.

java.lang.IndexOutOfBoundsException: Inconsistencia detectada. Posición de elemento no válida 86 (desplazamiento: 86). Estado: 100

Inicialmente tenía 100 elementos y eliminé algunos elementos del hilo de fondo.

Parece que Recyclerview llama a getItemCount () para validar el estado.


Me doy cuenta de que, para mí, esta excepción se produce cuando ocurren dos cosas al mismo tiempo, es decir

1) Desplazamiento de la vista de reciclaje

2) cambio de conjunto de datos

Entonces, resolví este problema deshabilitando el desplazamiento hasta que se llame a notifydatasetchanged.

leaderAdapter.notifyDataSetChanged(); pDialog.hide();

Para deshabilitar el desplazamiento, he utilizado un cuadro de diálogo de progreso, cuyo setCancelable es falso.

pDialog = new ProgressDialog(getActivity()); pDialog.setMessage("Please wait..."); pDialog.setCancelable(false);

El truco aquí es habilitar el desplazamiento solo cuando el conjunto de datos se haya actualizado.


No es problema para mí. Use NotifyDataSetChanged ();

public class MyFragment extends Fragment{ private MyAdapter adapter; // Your code public void addArticle(){ ArrayList<Article> list = new ArrayList<Article>(); //Add one article in this list adapter.addArticleFirst(list); // or adapter.addArticleLast(list); } } public class ArticleAdapterRecycler extends RecyclerView.Adapter<ArticleAdapterRecycler.ViewHolder> { private ArrayList<Article> Articles = new ArrayList<Article>(); private Context context; // Some functions from RecyclerView.Adapter<ArticleAdapterRecycler.ViewHolder> // Add at the top of the list. public void addArticleFirst(ArrayList<Article> list) { Articles.addAll(0, list); notifyDataSetChanged(); } // Add at the end of the list. public void addArticleLast(ArrayList<Article> list) { Articles.addAll(Articles.size(), list); notifyDataSetChanged(); } }


No veo nada incorrecto con el código que publicaste. Lo único extraño para mí es esta línea

setSelected(fileHolder.itemView, mSelectedArray.get(i));

en su método onBindViewHolder en el adaptador ... ¿está actualizando esta matriz también cuando cambia el tamaño de su lista de elementos en la matriz?


Obtuve esto para trabajar usando la sugerencia de Cocorico en una respuesta anterior ( https://.com/a/26927186/3660638 ) pero hay un problema: ya que estoy usando una SortedList , usando notifyDataSetChanged () cada vez que hay un cambio en los datos (agregar, eliminar, etc.) te hace perder las animaciones de elementos que obtienes con notifyItemXXXXX(position) , así que lo que terminé haciendo fue usarlo solo cuando cambio los datos en lote, como:

public void addAll(SortedList<Entity> items) { movieList.beginBatchedUpdates(); for (int i = 0; i < items.size(); i++) { movieList.add(items.get(i)); } movieList.endBatchedUpdates(); notifyDataSetChanged(); }




Tengo el mismo problema con este problema, estoy muy cansado de buscarlo y resolverlo. Pero he encontrado una respuesta para resolver y las excepciones no se han descartado nuevamente.

public class MyLinearLayoutManager extends LinearLayoutManager { public MyLinearLayoutManager(Context context) { super(context); } public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } public MyLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public boolean supportsPredictiveItemAnimations() { return false; } @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { //override this method and implement code as below try { super.onLayoutChildren(recycler, state); } catch (Exception e) { e.printStackTrace(); } } }

Espero que esta respuesta resuelva tu problema.


Tuve el mismo problema cuando configuré una nueva instancia de adaptador según algunos criterios de selección.

He solucionado mi problema utilizando RecyclerView.swapAdapter(adapter, true) cuando configuramos un nuevo adaptador.


Tuve un problema similar al intentar agregar el primer elemento en recyclerView con el método notifyItemInserted, así que modifiqué la función addItem en mi adaptador como se muestra a continuación y se resolvió.

Problema extraño, ¡espero que se solucione pronto!

public void addItem(int position, TableItem item) { boolean firstEntry = false; if (items.size() == 0) { firstEntry = true; } items.add(position, item); if (firstEntry) { notifyDataSetChanged(); } else { notifyItemInserted(position); } }


Tuve un problema similar pero con la eliminación de los contenidos. También quería mantener las animaciones también. Terminé usando el método NoticeRemove, luego pasé el rango. Esto parece solucionar cualquier problema ...

public void deleteItem(int index) { try{ mDataset.remove(index); notifyItemRemoved(index); notifyItemRangeRemoved(index,1); } catch (IndexOutOfBoundsException e){ notifyDataSetChanged(); e.printStackTrace(); } }

Parece estar trabajando y deshacerse de la excepción IOB ...


crear CustomLinearLayoutManager:

public class CustomLinearLayoutManager extends LinearLayoutManager { public CustomLinearLayoutManager(Context context) { super(context); } public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } public CustomLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public boolean supportsPredictiveItemAnimations() { return false; } public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { try { super.onLayoutChildren(recycler, state); } catch (IndexOutOfBoundsException e) { e.printStackTrace(); } } @Override public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { try { return super.scrollVerticallyBy(dy, recycler, state); } catch (Exception e) { e.printStackTrace(); } return 0; } }


haga esto cuando desee agregar una vista (como notifyData o addView o algo así)

if(isAdded()){ // // add view like this. // // celebrityActionAdapter.notifyItemRangeInserted(pageSize, 10); // // }


hay una oración en el código de sonido:
/ ** * Se usa cuando LayoutState se construye en un estado de desplazamiento. Debe * establecerse la cantidad de desplazamiento que podemos hacer sin crear una nueva * vista. Configuración necesaria para el reciclaje eficiente de la vista. * / int mScrollingOffset;


intente usar una bandera booleana, inicialícela como falsa y dentro del método OnRefresh hágalo verdadera, borre su lista de datos si la bandera es verdadera justo antes de agregarle los nuevos datos y luego hágalo falsa.

tu código podría ser así

private boolean pullToRefreshFlag = false ; private ArrayList<your object> dataList ; private Adapter adapter ; public class myClass extend Fragment implements SwipeRefreshLayout.OnRefreshListener{ private void requestUpdateList() { if (pullToRefresh) { dataList.clear pullToRefreshFlag = false; } dataList.addAll(your data); adapter.notifyDataSetChanged; @Override OnRefresh() { PullToRefreshFlag = true reqUpdateList() ; } }


Editar: el error se ha solucionado ahora, si aún obtiene la misma excepción, asegúrese de actualizar su fuente de datos del adaptador solo desde el hilo principal y de llamar al método de notificación del adaptador adecuado después.

Respuesta anterior: Parece ser un error en RecyclerView , se informa here y here . Esperemos que se solucione en la próxima versión.