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

A cambiar el contenido de RecyclerView, me reemplazar Cadenas en mItemList y llame a notifyDataSetChanged() en RecyclerViewAdapter.

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

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

Aquí el completo seguimiento de la pila de 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)

AdapterView 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;
}
}
  • por favor enviar su adaptador de código y cómo utilizarlo
  • Puedo publicar mi solución en este otro hilo
InformationsquelleAutor jimmy0251 | 2014-11-09

25 Comentarios

  1. 37

    Edición: El error se ha corregido ahora, si usted todavía está recibiendo la misma Excepción, por favor asegúrese de que usted está actualizando su Adaptador de la fuente de datos sólo desde el hilo principal y llamar adaptador adecuado método de notificación después de ella.

    Viejo respuesta: parece ser un error en RecyclerView, se informó aquí y aquí. Ojalá que será corregido en la próxima versión.

    • No hay solución hasta que la próxima versión será lanzado?
    • Todavía se enfrenta el problema .. 🙁
    • Sospecho que esto tiene algo que ver con tener la RecyclerView dentro de un ScrollView. También he experimentado pero no estoy seguro. Trate de cambiar el diseño y ver si esto ayuda?
    • estoy usando compilar ‘com.android.apoyo:recyclerview-v7:23.0.0’, pero todavía se enfrentan el mismo problema.?
    • Usted se enfrentará con el mismo problema si intenta cambiar el contenido de la lista de subproceso en segundo plano.
    • todavía unreolved 😀 tengo faound un trabajo alrededor de este, pero amablemente ¿por qué no podemos cambiar la lista de otro subproceso/actividad/fragmento y el adaptador puede tomar tomar de más que todos los que estamos llamando notifyDataSet… suspiro…..
    • No es un error y creo que no se fija en las próximas versiones. Ver mi respuesta por favor.

  2. 17

    Ningún problema para mí. Uso 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();
    }
    }
    • El chico guardar mi día : ). Gracias de antemano!
    • Una cosa a tener en cuenta al utilizar notifyDataSetChanged() es que no va a animar alteración de los elementos por defecto, mientras que notifyItemChanged() voluntad.
    • Yo tenía el mismo error al intentar insertar elementos en el adaptador y el uso notifyItemRangeInserted(0, newNotifications.size()); en vacío de un adaptador. He resuelto este problema mediante la comprobación de si el adaptador está vacía, a continuación, utilizar notifydatasetchanged, de lo contrario usar notifyItemRangeInserted(0, newNotifications.size());
    • notifyDataSetChanged también animar objetos si hacer 2 cosas: 1) llame setHasStableIds(true) en el Adaptador y 2)reemplazar getItemid para devolver un único valor largo de su Adaptador para cada fila, una vez hecho esto, se ll desencadenar las animaciones
  3. 10

    Acaba de prohibir RecyclerView del desplazamiento cuando los datos está cambiando.

    Como mi código:

    mRecyclerView.setOnTouchListener(
    new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
    if (mIsRefreshing) {
    return true;
    } else {
    return false;
    }
    }
    }
    );

    Más sobre: http://drakeet.me/recyclerview-bug-indexoutofboundsexception-inconsistency-detected-invalid-item-position-solution

    • ¿Qué es mIsRefreshing?
    • parece ser un indicador booleano para indicar cuando la actualización ha comenzado, pero aún no ha terminado.
    • notifyDataSetChanged(); trabajó para mí
    • el enlace está muerto. Y donde puedo hacer mIsRefreshing = true ?
  4. 7

    Aunque un par de útiles hipervínculos acerca de este tema en la aceptó respuesta, no es cierto que este comportamiento de RecyclerView mientras que el desplazamiento es un error.

    Si usted ve esta excepción, es más probable que usted olvide notificar el adaptador después de que el contenido de RecyclerView se «cambia». La gente llama notifyDataSetChanged() sólo después de que se agrega un elemento del conjunto de datos. Sin embargo, la contradicción no sólo se produce después de llenar el adaptador, pero también cuando se quita un elemento o desactiva el conjunto de datos, se debe actualizar la vista, notificando el adaptador sobre este cambio:

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

    En mi caso, traté de limpiar el adaptador en onStop(), y la reposición en onStart(). Se me olvidó llamar a notifyDataSetChanged() después de que el adaptador se limpia mediante el uso de clear(). Entonces, cada vez que cambia el estado de onStop() a onStart() y rápidamente desplazado el RecyclerView mientras que el conjunto de datos es la recarga, vi a esta excepción. Si esperé el final de la recarga sin necesidad de desplazarse, no sería la excepción, ya que el adaptador puede ser reintegrados bien esta vez.

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

    • Finalmente, algunos trabajando solución para este problema. Gracias Hombre!
    • problema y la solución están muy bien explicadas. Gracias hombre.
  5. 5

    El problema no es, definitivamente, porque de recyclerview de desplazamiento, sino que está relacionado con la notifyDataSetChanged(). Yo tenía un reciclador de vista en el que yo estaba constantemente cambiando de datos, por ejemplo, la adición y eliminación de datos. Me estaba llamando notifyDataSetChanged() cada vez que yo era la adición de elementos a mi lista, Pero no fue actualizar el adaptador de siempre que el elemento que está siendo retirado o en la lista se borra.

    Así que para solucionar 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)

    Me llama adaptador.notifyDataSetChanged() después de la lista.clear(), donde era necesario.

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

    Desde entonces, nunca he encontrado la excepción.
    Espero que funcione de la misma para los demás. 🙂

    • Mi placer 😀
  6. 4

    Yo estaba frente a un mismo problema, java.lang.IndexOutOfBoundsException: Inconsistencia detectada.

    Crear Personalizado 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 los ayude.

    • Todavía se me pone la excepción después de probar su respuesta, pero la probabilidad de que este error se ha reducido mucho. Voy a utilizar tu manera de solucionar este problema, en mi aplicación, la esperanza de que los evaluadores no detectar el error.
    • espero 🙂
    • ¿se solucionó el problema?
  7. 3

    Tuve un problema similar pero con la eliminación de los contenidos. Yo también quería mantener las animaciones también. Terminé usando el notifyRemove, pasando luego a la gama. 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 funcionando y deshacerse de la IOB Excepción…

    • ¿Por qué estás quitando dos veces?
  8. 3

    Me figura que, para mí, esta excepción se produce cuando dos cosas sucede, al mismo tiempo, es decir,

    1) el Desplazamiento de recyclerview

    2) conjunto de datos para cambiar

    Así, he resuelto este problema mediante la desactivación de la desplácese hasta el notifydatasetchanged se llama.

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

    Para desactivar el desplazamiento, he utilizado un diálogo de progreso, cuya setCancelable es falso.

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

    El truco aquí es permitir el desplazamiento sólo cuando el conjunto de datos ha sido actualizada.

  9. 3

    Este problema está llegando a recyclerview si utiliza

    adapter.setHasStableIds(true);

    si se establece así, quite esto, y para actualizar el conjunto de datos dentro del adaptador;


    si usted todavía se enfrentan a la cuestión, la anulación de todas las vistas una vez que obtener nuevos datos y, a continuación, actualizar el conjunto de datos.

    • Este debe ser publicado como la respuesta correcta!
  10. 2

    Tengo este trabajo el uso de Cócora sugerencia en una respuesta anterior (https://stackoverflow.com/a/26927186/3660638) pero hay un problema: ya estoy usando un SortedList, utilizando notifyDataSetChanged() cada vez que hay un cambio en los datos (añadir, eliminar, etc) te hace perder el elemento de animaciones que puedes obtener con notifyItemXXXXX(position), así que lo que terminé haciendo fue utilizando sólo cuando puedo cambiar los datos en batch, 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();
    }  
  11. 2

    Debe utilizar en su getitem contar

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

    También actualizar el reciclador de vista por favor, utilice este

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

    Con esta solución usted no es capaz de resolver el problema
    usted simplemente utilizar una condición dentro de la onBindViewHolder para resolver el 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);
    }
    }
  12. 2

    Yo soy la alteración de datos para la RecyclerView en el fondo Thread. Tengo el mismo Exception como el OP. He añadido este después de cambiar los datos:

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

    Espero que ayude

  13. 1

    Tuve el mismo problema cuando me estaba preparando nueva instancia del adaptador basado en algunos criterios de selección.

    He solucionado mi problema mediante el uso de RecyclerView.swapAdapter(adapter, true)
    Cuando nos pusimos de nuevo adaptador.

  14. 1

    Tengo el mismo problema con este problema, estoy muy cansado de buscar y resolver. Pero no he encontrado respuesta para resolver y excepciones no han sido expulsados de nuevo.

    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 va a ser resolver su problema.

  15. 1

    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;
    }
    }
  16. 1

    Me han replicado este problema.
    Esto sucedió cuando nos quitar elementos en el subproceso de fondo de mList pero no llame a notifyDataSetChanged(). Ahora Si nos desplazamos Esta excepción está llegando.

    java.lang.IndexOutOfBoundsException: la Inconsistencia detectada. Elemento no válido posición 86(offset:86).estado:100

    Inicialmente, tenía 100 artículos y eliminado algunos elementos de fondo de la rosca.

    Parece Recyclerview llamadas getItemCount() sí para validar el estado.

  17. 1

    Evitar notifyDatasetHasChanged() y hacer 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());
    }
  18. 0

    Yo no veo anthing mal con el código que has publicado. La única cosa extraña para mí es esta línea

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

    en su onBindViewHolder método en el adaptador.. se va a actualizar esta matriz también cuando se cambia el tamaño de la lista de elementos en la matriz?

    • No, sólo los cambios de fondo de la vista.
    • Sé lo que se hace u.u lo que me preguntó fue si estaban actualizando mSelectedArray así cuando cambia el tamaño de los elementos en el adaptador.. el arrayindex fuera de los límites podría venir de fuera de ella
    • Aquí está el código del método : private static void setSelected(Vista, boolean isSelected) { if (vista != null) ver.setSelected(isSelected); }
    • De nuevo, yo sé lo que hace… =>>>> lo que yo preguntaba era si estaban actualizando mSelectedArray así cuando cambia el tamaño de los elementos en el adaptador.. el arrayindex fuera de los límites podría venir de fuera de ella
    • No, no estoy actualizando mSelectedArray.
    • si desea cambiar el tamaño de los elementos en el adaptador se debe cambiar también
    • SparseBooleanArray devuelve falso si no contienen una posición, no una Excepción.

  19. 0

    He tenido un problema similar, mientras que yo intente agregar primer elemento en recyclerView con notifyItemInserted método, así que he modificado addItem función en mi adaptador a continuación y que se resuelva.

    Problema raro, la esperanza de que va a ser solucionado pronto pensamiento de car!

    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);
    }
    }
  20. 0

    hay una frase en código de sonido :

    /**
    * Se utiliza cuando LayoutState está construido en un desplazamiento del estado. Se debe
    * se establece la cantidad de desplazamiento que podemos hacer sin necesidad de crear una nueva
    * ver. La configuración de este es necesario para la eficiente vista de reciclaje.
    */
    int mScrollingOffset; 

  21. 0

    En mi caso es resuelto por un cambio de
    mRecyclerView.smoothScrollToPosition(0) a

    mRecyclerView.scrollToPosition(0)
  22. 0

    intente utilizar un indicador booleano, inicializar como falso y dentro de OnRefresh método que sea cierto, claro que su dataList si la bandera es cierto justo antes de añadir los nuevos datos y después que hacen que sea falsa.

    el código podría ser como este

     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() ; 
    }
    }
  23. 0

    En mi caso el problema era yo.

    Mi configuración es un Recyclerview, Adaptador & Cursor/mecanismo del Cargador.

    A un punto en mi Aplicación el cargador está destruido.

    supportLoaderManager.destroyLoader(LOADER_ID_EVENTS)

    Yo estaba esperando el Recyclerview mostrará una lista vacía desde que me acaba de eliminar de su origen de datos. Lo que hace que el error de encontrar más complicado fue, que la lista era visible y la conocida Excepción producido sólo en una aventura de desplazamiento//animación.

    Que me costó un par de horas. 🙂

  24. 0

    hacer esto cuando usted desea agregar vista(como notifyData o addView o algo así)

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

Dejar respuesta

Please enter your comment!
Please enter your name here