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
}