Medthodに関するRecyclerView
ドキュメントによると notifyItemChanged(int position、Object payload)
オプションのペイロードオブジェクトを使用して、位置のアイテムが変更されたことを登録済みのオブザーバーに通知します。
このメソッドで2番目のパラメーターpayload
を使用する方法がわかりません。 「ペイロード」に関する多くのドキュメントを検索しましたが、すべてがあいまいでした。
ですから、この方法を知っているなら、それについて明確な例を示してください。どうもありがとうございました。
機能を示すこのサンプルコードをご覧ください。これは、RecyclerView
の位置にあるアイテムがクリックされたときにnotifyItemChanged(position, payload)
を呼び出すposition
です。 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'
}
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 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);
}
}
_
そして、コードのどこかでアダプターを呼び出して更新しますsingleTextView-tvScore
_mRecyclerViewAdapter.notifyItemChanged(position, new Integer(4533));
_
[...]
onBindViewHolder(ViewHolderホルダー、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);
_
ViewHolder
メソッドが呼び出されたときにonBindViewHolder
のデータに対して部分的な更新を実行するだけの場合は、「オプションのペイロードオブジェクト」を渡すことができます。ただし、たとえばビューがアタッチされていない場合など、ペイロードが常に渡されるかどうかは不明なので、さらに確認する必要があります。
とにかく、null
を渡すと、アイテムの完全な更新が実行されるので、心配する必要はありません。