Selon RecyclerView
documentation sur medthod notifyItemChanged (int position, charge utile)
Avertissez tous les observateurs inscrits que l'élément à la position a été modifié avec un objet de charge utile facultatif.
Je ne comprends pas comment utiliser le second paramètre payload
dans cette méthode. J'ai cherché de nombreux documents sur "charge utile" mais tout était ambigu.
Donc, si vous connaissez cette méthode, montrez-moi un exemple clair à ce sujet. Merci beaucoup.
Consultez cet exemple de code qui illustre la fonctionnalité. C'est un RecyclerView
qui appelle notifyItemChanged(position, payload)
lorsque l'élément à la position position
est cliqué. Vous pouvez vérifier que onBindViewHolder(holder, position, payload)
a été appelé en recherchant l'instruction logcat.
Assurez-vous que vous utilisez au moins la version 23.1.1
des bibliothèques de support, comme ceci:
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>
Si vous souhaitez mettre à jour pas tous le détenteur mais juste ne partie, cette méthode est ce dont vous avez besoin.
Image que vous avez suivante ViewHolder
public class ViewHolder extends RecyclerView.ViewHolder {
public final TextView tvPlayer;
public final TextView tvScore;
public ViewHolder(View view) {
super(view);
tvPlayer = (TextView) view.findViewById(R.id.tv_player);
tvScore = (TextView) view.findViewById(R.id.tv_score);
}
}
Et quelque part dans votre code, vous appelez un adaptateur pour mettre à jour single TextView - tvScore
mRecyclerViewAdapter.notifyItemChanged(position, new Integer(4533));
[...]
( onBindViewHolder (titulaire de ViewHolder, position int, liste des charges utiles)) intercepte le rappel au premier abord. Si payloads
ne correspond pas à vos besoins, vous devez obligatoirement appeler la super-classe super.onBindViewHolder(holder,position, payloads);
qui déclenchera onBindViewHolder(ViewHolder holder, int position)
pour les autres cas.
// 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
}
En gros, il est beaucoup plus pratique de traiter les charges utiles comme des constantes.
Vous n’avez pas besoin de transmettre de données si celles-ci ont déjà été modifiées dans le jeu de données.
Créez donc deux constantes:
public static final String PAYLOAD_NAME = "PAYLOAD_NAME";
public static final String PAYLOAD_AGE = "PAYLOAD_AGE";
Ensuite, dans l'adaptateur, en plus d'une onBindViewHolder(YourViweHolder holder, int position)
normale où vous mettez à jour tout l'élément, par exemple:
@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()));
}
vous implémentez également:
@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);
}
}
Vous pouvez gérer autant de cas que nécessaire et mettre à jour uniquement les vues réellement modifiées.
La dernière étape - vous venez de faire:
adapter.notifyItemChanged(somePosition, YourAdapter.PAYLOAD_NAME);
Vous pouvez passer un "objet de charge optionnel" lorsque vous souhaitez simplement effectuer une mise à jour partielle des données dans le ViewHolder
lorsque la méthode onBindViewHolder
est appelée. Toutefois, il n’est pas certain que les données utiles seront toujours transmises, par exemple si la vue n’est pas attachée. Vous devez donc effectuer quelques vérifications supplémentaires.
Quoi qu'il en soit, si vous passez null
, une mise à jour complète de l'élément sera effectuée et vous n'aurez pas à vous en préoccuper.