recyclerview android android-recyclerview payload

recyclerview - notifydatasetchanged android



Necesita un ejemplo sobre RecyclerView.Adapter.notifyItemChanged(int position, Object payload) (4)

De acuerdo con la documentación de RecyclerView sobre medthod notifyItemChanged (int position, Object payload)

Notifique a los observadores registrados que el elemento en la posición ha cambiado con un objeto de carga útil opcional.

No entiendo cómo usar la segunda payload parámetro en este método. He buscado muchos documentos sobre "carga útil", pero todo era ambiguo.

Entonces, si conoce este método, por favor muéstreme un claro ejemplo al respecto. Muchas gracias.


Básicamente, es mucho más conveniente tratar las cargas útiles como constantes.
No tiene que pasar ningún dato allí si ya ha cambiado en el conjunto de datos.
Entonces, crea un par de constantes:

public static final String PAYLOAD_NAME = "PAYLOAD_NAME"; public static final String PAYLOAD_AGE = "PAYLOAD_AGE";

Luego, en el adaptador, además de un onBindViewHolder(YourViweHolder holder, int position) donde actualizas el ítem completo, por ejemplo:

@Override public void onBindViewHolder(final YourViewHolder holder, final int position) { final YourItem item = getItem(position); holder.tvName.setText(item.getName()); holder.tvAge.setText(String.valueOf(item.getAge())); }

también implementas:

@Override public void onBindViewHolder(final YourViewHolder holder, final int position, final List<Object> payloads) { if (!payloads.isEmpty()) { final YourItem item = getItem(position); for (final Object payload : payloads) { if (payload.equals(PAYLOAD_NAME)) { // in this case only name will be updated holder.tvName.setText(item.getName()); } else if (payload.equals(PAYLOAD_AGE)) { // only age will be updated holder.tvAge.setText(String.valueOf(item.getAge())); } } } else { // in this case regular onBindViewHolder will be called super.onBindViewHolder(holder, position, payloads); } }

Puede manejar tantos casos como necesite y actualizar solo las vistas que realmente cambiaron.
El último paso, simplemente lo haces:

adapter.notifyItemChanged(somePosition, YourAdapter.PAYLOAD_NAME);


Echa un vistazo a este código de muestra que demuestra la característica. Es un RecyclerView que llama a notifyItemChanged(position, payload) cuando se hace clic en el elemento en la posición de position . Puede verificar que se onBindViewHolder(holder, position, payload) buscando la declaración de logcat.

Asegúrese de estar utilizando al menos la versión 23.1.1 de las bibliotecas de soporte, así:

dependencies { compile fileTree(dir: ''libs'', include: [''*.jar'']) compile ''com.android.support:appcompat-v7:23.1.1'' compile ''com.android.support:recyclerview-v7:23.1.1'' compile ''com.android.support:cardview-v7:23.1.1'' }

HelloActivity.java

package com.formagrid.hellotest; import android.app.Activity; import android.os.Bundle; import android.support.v7.widget.CardView; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; public class HelloActivity extends Activity { private RecyclerView mRecyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); mRecyclerView.setAdapter(new HelloAdapter()); DefaultItemAnimator animator = new DefaultItemAnimator() { @Override public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) { return true; } }; mRecyclerView.setItemAnimator(animator); } private static class HelloAdapter extends RecyclerView.Adapter<HelloAdapter.HelloViewHolder> { public class HelloViewHolder extends RecyclerView.ViewHolder { public TextView textView; public HelloViewHolder(CardView cardView) { super(cardView); textView = (TextView) cardView.findViewById(R.id.text_view); } } @Override public HelloViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate( R.layout.card_item, parent, false); return new HelloViewHolder(cardView); } @Override public void onBindViewHolder(HelloViewHolder holder, int position) { bind(holder); } @Override public void onBindViewHolder(HelloViewHolder holder, int position, List<Object> payload) { Log.d("butt", "payload " + payload.toString()); bind(holder); } @Override public int getItemCount() { return 20; } private void bind(final HelloViewHolder holder) { holder.textView.setText("item " + holder.getAdapterPosition()); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int position = holder.getAdapterPosition(); Log.d("butt", "click " + position); HelloAdapter.this.notifyItemChanged(position, "payload " + position); } }); } } }

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".HelloActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>

card_item.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="100dip" android:layout_margin="5dip" card_view:cardElevation="5dip"> <TextView android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.v7.widget.CardView>


Puede pasar un "objeto de carga útil opcional" cuando solo desea realizar una actualización parcial de los datos en el ViewHolder cuando se onBindViewHolder método onBindViewHolder . Sin embargo, no es seguro que la carga útil siempre se pase, por ejemplo, si la vista no está adjunta, por lo que debería realizar algunas verificaciones más.

De todos modos, si pasa null , se realizará una actualización completa del elemento y no tendrá que preocuparse por ello.


Si desea actualizar no toda la vista del titular sino solo una parte , este método es lo que necesita.

Imagen que tienes siguiendo a ViewHolder

public class ViewHolder extends RecyclerView.ViewHolder { public final TextView tvName; public final TextView tvScore; public ViewHolder(View view) { super(view); tvName = (TextView) view.findViewById(R.id.tv_name); tvScore = (TextView) view.findViewById(R.id.tv_score); } }

Y en algún lugar de tu código llamas al adaptador para actualizar solo TextView - tvScore

mRecyclerViewAdapter.notifyItemChanged(position, new Integer(4533));

[...]

onBindViewHolder (ViewHolder holder, int position, List Payloads) capta la devolución de llamada al principio. Si las payloads no coinciden con sus requisitos, tiene que hacer una llamada obligatoria a super clase super.onBindViewHolder(holder,position, payloads); que desencadenan onBindViewHolder(ViewHolder holder, int position) para otros casos.

// Update only part of ViewHolder that you are interested in // Invoked before onBindViewHolder(ViewHolder holder, int position) @Override public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) { if(!payloads.isEmpty()) { if (payloads.get(0) instanceof Integer) { holder.tvScore.setText(String.valueOf((Integer)payloads.get(0))) } }else { super.onBindViewHolder(holder,position, payloads); } } // Update ALL VIEW holder @Override public void onBindViewHolder(ViewHolder holder, int position) { MItem item = mList.get(position) // some update }