recyclerview make how create cardview card and android android-support-library android-adapter android-recyclerview

make - recyclerview android kotlin



RecyclerView.Adapter.notifyItemChanged() nunca pasa la carga Ăștil a onBindViewHolder() (4)

¿Por qué no simplemente usar RecyclerView.Adapter.notifyItemChanged(int position) los documentos parece un poco ambiguo al mencionar

RecyclerView.Adapter.notifyItemChanged(int position,Object payload)

El cliente puede opcionalmente pasar una carga útil para un cambio parcial. Estas cargas útiles se fusionarán y se pueden pasar a onBindViewHolder del adaptador (ViewHolder, int, List)

por lo tanto, no está garantizado que recibirá la Lista en su onBindViewHolder

Estoy intentando actualizar un ViewHolder en un RecyclerView sin ViewHolder a ViewHolder todo. De acuerdo con los documentos, debo hacer esto llamando a RecyclerView.Adapter.notifyItemChanged(int position, Object payload) , donde payload es un objeto arbitrario que se pasará a RecyclerView.Adapter.onBindViewHolder(VH holder, int position, List<Object> payloads) , donde podré actualizar ViewHolder.

Pero cuando intento esto, onBindViewHolder siempre recibe una lista vacía. Entre estas dos llamadas, se borra la lista interna de cargas útiles. Después de establecer puntos de interrupción en el código fuente de RecyclerView, esto sucede debido a una retransmisión, que eventualmente llama a RecyclerView.ViewHolder.clearPayload()

¿Alguien más ha logrado que esto funcione? ¿Se trata de un error en la biblioteca de soporte o es algo que he hecho para activar una retransmisión entre estas dos funciones?

Aquí está el seguimiento de la pila para cuando se borra la carga útil:

"<1> main@831692616832" prio=5 runnable java.lang.Thread.State: RUNNABLE at android.support.v7.widget.RecyclerView$ViewHolder.clearPayload(RecyclerView.java:8524) at android.support.v7.widget.RecyclerView$ViewHolder.resetInternal(RecyclerView.java:8553) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4544) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4461) at android.support.v7.widget.LayoutState.next(LayoutState.java:86) at android.support.v7.widget.StaggeredGridLayoutManager.fill(StaggeredGridLayoutManager.java:1423) at android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.java:610) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2847) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3145) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:581) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.FrameLayout.onLayout(FrameLayout.java:448) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.FrameLayout.onLayout(FrameLayout.java:448) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.FrameLayout.onLayout(FrameLayout.java:448) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.FrameLayout.onLayout(FrameLayout.java:448) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1043) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.FrameLayout.onLayout(FrameLayout.java:448) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.FrameLayout.onLayout(FrameLayout.java:448) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.widget.FrameLayout.onLayout(FrameLayout.java:448) at android.view.View.layout(View.java:14289) at android.view.ViewGroup.layout(ViewGroup.java:4562) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1976) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1730) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1004) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5481) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) at android.view.Choreographer.doCallbacks(Choreographer.java:562) at android.view.Choreographer.doFrame(Choreographer.java:532) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5103) at java.lang.reflect.Method.invokeNative(Method.java:-1) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(NativeStart.java:-1)


En algunos casos, funcionó con notifyItemRangeChanged(getItemRealCount(), 1) .


Si utiliza el animador de elementos (de forma predeterminada, está habilitado), la carga útil estará siempre vacía. Mira esta respuesta en el tracker de Android :

Así es como se diseña la carga útil del trabajo. Solo se pasa a on bind "si estamos volviendo a enlazar con el mismo titular de vista". Lo mismo para el enlace de datos, si no está vinculado al mismo titular de vista, no puede hacer el enlace de forma incremental. En el caso de animaciones de cambio, RV crea dos copias de la Vista para el fundido cruzado, de modo que no esté enlazado con el mismo VH en el postLayout.

Pronto, proporcionaremos una API para ejecutar animaciones de cambio dentro del mismo ViewHolder.

Por lo tanto, hasta que compartan esta nueva API, necesitamos usar algo como esto:

mRecyclerView.setItemAnimator(null);

editar: vea el comentario de @blindOSX, donde se dio cuenta de que para habilitar las cargas útiles, solo puede deshabilitar las animaciones de eventos de cambio de elementos.

edit2: Parece que han actualizado este comportamiento sin previo aviso. Ver respuesta actualizada @Patricia Li .


RecyclerView crea de forma predeterminada otra copia de ViewHolder para que las vistas se ViewHolder entre sí. Esto causa el problema porque el antiguo ViewHolder obtiene la carga útil, pero luego el nuevo no. Así que necesitas decirle explícitamente que reutilice el anterior:

DefaultItemAnimator animator = new DefaultItemAnimator() { @Override public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) { return true; } }; mRecyclerView.setItemAnimator(animator);