需要一个关于回收视图.Adapter.notifyItemChanged (int 位置,对象有效负载)的示例

根据 RecyclerView关于方法 NotifyItemChanged (int 位置,对象有效负载)的文档

通知任何已注册的观察者,位置上的物品已经随着一个可选的有效载荷对象而改变。

我不明白如何在这个方法中使用第二个参数 payload。我已经搜索了许多关于“有效载荷”的文档,但一切都是模棱两可的。

所以,如果你知道这个方法,请给我一个明确的例子。非常感谢。

59690 次浏览

当您只想在调用 onBindViewHolder方法时对 ViewHolder中的数据执行部分更新时,可以传入一个“可选的有效负载对象”。但是,它不能确定有效负载是否总是会被传递,例如,如果视图没有附加,那么您应该执行更多的检查。

无论如何,如果你通过 null,它将执行一个项目的完整更新,你不必担心它。

请查看演示该特性的示例代码。它是一个 RecyclerView,当单击位置为 position的项时调用 notifyItemChanged(position, payload)。您可以通过查找 logcat 语句来验证调用了 onBindViewHolder(holder, position, payload)

确保至少使用了支持库的 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'
}

Hello Activity.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>

如果您想更新 不全是持有者视图,但只更新 一部分,那么这个方法正是您所需要的。

图像,你有下面的 视图持有人

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


}

在代码中的某个位置调用适配器来更新 单身 TextView-tvScore

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

[...]

OnBindViewHolder (ViewHolder holder,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
}

基本上,将有效载荷视为常量要方便得多。
如果数据集中的数据已经更改,则不必在此处传递任何数据。
那么,创建几个常量:

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