2015-10-16 21 views
21

Innanzitutto, mi dispiace per il mio inglese. Secondo RecyclerView documentazione relativa medthod notifyItemChanged(int position, Object payload)È necessario un esempio su RecyclerView.Adapter.notifyItemChanged (posizione int, carico utile dell'oggetto)

Segnalatemi eventuali osservatori registrati che l'elemento in posizione è cambiata con un oggetto carico opzionale.

Non capisco come utilizzare il secondo paramenter payload in questo metodo. Ho cercato molti documenti su "payload" ma tutto era ambiguo.

Quindi, se si conosce questo metodo, si prega di mostrarmi un chiaro esempio a riguardo. Grazie mille.

risposta

19

Dai un'occhiata a questo codice di esempio che dimostra la funzionalità. È un RecyclerView che chiama notifyItemChanged(position, payload) quando si fa clic sull'elemento nella posizione position. È possibile verificare che onBindViewHolder(holder, position, payload) sia stato chiamato cercando l'istruzione logcat.

Assicurarsi che si sta utilizzando almeno la versione 23.1.1 delle librerie di supporto, in questo modo:

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> 
+1

Ho appena testato il codice. C'è qualcosa di inutile nel mio test: il basic onBind (senza payload) non viene mai chiamato. Adesso perché? Ho appena chiamato notifyItemRangeChanged (index, mArrayList.size()); oppure notifyItemInserted (i); – Cocorico

+4

ama il tag di registro immaturo +1 – styler1972

1

È possibile passare in un "oggetto payload opzionale" quando si desidera eseguire un aggiornamento parziale dei dati nello ViewHolder quando viene chiamato il metodo onBindViewHolder. Tuttavia, non è sicuro che il payload verrà sempre passato, ad esempio se la vista non è allegata, quindi è necessario eseguire ulteriori controlli.

In ogni caso, se si passa null verrà eseguito un aggiornamento completo dell'articolo e non sarà necessario preoccuparsene.

26

Se si desidera aggiornare non tutti titolare View, ma solo una parte di esso , questo metodo è quello che ti serve.

Immagine che siano presenti i seguenti 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); 
     } 

    } 

E da qualche parte nel codice vi invito adattatore per aggiornare singoloTextView - tvScore

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

[...]

onBindViewHolder (ViewHolder holder, int position, List payloads) cattura la funzione di call all'inizio. Se payloads non corrisponde ai tuoi requisiti devi chiamare obbligatoriamente super classe super.onBindViewHolder(holder,position, payloads); che attiva onBindViewHolder(ViewHolder holder, int position) per altri casi.

 // 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 
     } 
+1

Che meravigliosa risposta! – wonsuc

+1

Perché è un elenco di payload, però? In tal caso hai più di un oggetto nella lista? Nel caso in cui chiami notifyItemChanged più volte nella stessa posizione? –

+0

Se stai usando Kotlin, c'è un indizio sul fatto che il payload è di tipo "Any" e in Java è "Object", quindi puoi passare lì tutto quello che vuoi. In seguito, gli oggetti verranno gettati all'interno di 'onBindViewHolder (titolare di ViewHolder, posizione int, elenco payloads)'. Vedi di più su: https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemChanged(int, java.lang.Object) – murt