Нужен пример о RecyclerView.Адаптер.notifyItemChanged (int позиция, полезная нагрузка объекта)

по данным RecyclerView документация о medthod notifyItemChanged (int позиция, полезная нагрузка объекта)

уведомить всех зарегистрированных наблюдателей, что элемент в позиции изменился с дополнительным объектом полезной нагрузки.

Я не понимаю, как использовать второй параметр payload в этот метод. Я искал много документов о "полезной нагрузке", но все было неоднозначно.

Итак, если вы знаете об этом методе, пожалуйста, покажите мне наглядный пример об этом. Большое спасибо.

4 ответов


проверьте этот пример кода, который демонстрирует эту функцию. Это RecyclerView что называет notifyItemChanged(position, payload) когда деталь на положении это. Вы можете проверить это onBindViewHolder(holder, position, payload) был вызван путем поиска оператора logcat.

убедитесь, что вы используете хотя бы версию 23.1.1 библиотек поддержки, например:

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>

если вы хотите обновить Не все вид держателя, но просто часть этот метод является то, что вам нужно.

изображение, которое у вас есть следующие 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);
        }

    }

и где-то в вашем коде вы вызываете адаптер для обновления один TextView-tvScore

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

[...]

onBindViewHolder(держатель держателя, int позиция, список нагрузки) сначала ловит обратный вызов. Если payloads не соответствует вашим требованиям вы должны обязательно назвать супер класс super.onBindViewHolder(holder,position, payloads); спуск onBindViewHolder(ViewHolder holder, int position) для других случаев.

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

вы можете передать "дополнительный объект полезной нагрузки", когда вы просто хотите выполнить частичное обновление данных в ViewHolder когда onBindViewHolder метод называется. Однако он не уверен, что полезная нагрузка всегда будет передаваться, например, если представление не прикреплено, поэтому необходимо выполнить еще несколько проверок.

в любом случае, если вы проходите null будет выполнено полное обновление элемента, и вам не придется беспокоиться об этом.


в принципе, гораздо удобнее рассматривать полезные нагрузки как константы.
Вам не нужно передавать туда какие-либо данные, если они уже изменены в наборе данных.
Итак, создайте пару констант:

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

тогда в адаптере, кроме обычного onBindViewHolder(YourViweHolder holder, int position) где вы обновляете весь элемент, например:

@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()));
}

кроме того, вы реализуете:

@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);
    }
}

вы можете обрабатывать столько случаев, сколько вам нужно, и обновлять только представления, которые на самом деле измененный.
Последний шаг-вы просто делаете:

adapter.notifyItemChanged(somePosition, YourAdapter.PAYLOAD_NAME);