1、通过使用AsyncListDiffer类来达到只需要替换集合,不需要具体控制刷新的项
2、当一个Item内容改变时,需要新建一个对象,这样才能避免因对象地址一致导致Adapter无法判断内容更改。
3、当一个Item内容改变时,通过遍历集合替换改变的Item,使用ListIterator.set()更优雅。
public void onReplaceOne(View view) {
List<MultiItemBean> multiItemBeansReadOnly = mAdapter.getDiffer().getCurrentList();
List<MultiItemBean> multiItemBeansWritable = new ArrayList<>();
multiItemBeansWritable.addAll(multiItemBeansReadOnly);
//找到一个STATUS_ONE类型的
ListIterator<MultiItemBean> iterator = multiItemBeansWritable.listIterator();
MultiItemBean bean = null;
while (iterator.hasNext()) {
bean = iterator.next();
if (bean.getStatus() == MultiItemBean.STATUS_ONE && bean.getOne() != null) {
//想刷新同一项内容,必须new一个对象
bean = bean.duplicate();
MultiItemBean.One one = bean.getOne().duplicate();
one.setProgress(new Random().nextInt(100));
bean.setOne(one);
iterator.set(bean);
break;
}
}
mAdapter.getDiffer().submitList(multiItemBeansWritable);
}
4、局部刷新可以通过实现onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads)和DiffUtil.ItemCallback接口的
getChangePayload(@NonNull MultiItemBean oldItem, @NonNull MultiItemBean newItem)来实现。
package com.example.multiitemrefreshdemo.adapter;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.example.multiitemrefreshdemo.R;
import com.example.multiitemrefreshdemo.bean.MultiItemBean;
import java.util.List;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
public class NormalMultiItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = NormalMultiItemAdapter.class.getSimpleName();
private static final int TYPE_ONE = MultiItemBean.STATUS_ONE;
private static final int TYPE_TWO = MultiItemBean.STATUS_TWO;
private static final String KEY_PROGRESS = "progress";
private AsyncListDiffer<MultiItemBean> mDiffer;
public NormalMultiItemAdapter() {
mDiffer = new AsyncListDiffer<MultiItemBean>(this, new DiffUtil.ItemCallback<MultiItemBean>() {
@Override
public boolean areItemsTheSame(@NonNull MultiItemBean oldItem, @NonNull MultiItemBean newItem) {
boolean result = false;
if (oldItem.getOne() != null && newItem.getOne() != null) {
result = TextUtils.equals(oldItem.getOne().getName(), newItem.getOne().getName());
} else if (oldItem.getTwo() != null && newItem.getTwo() != null) {
result = TextUtils.equals(oldItem.getTwo().getName(), newItem.getTwo().getName());
}
Log.d(TAG, "areItemsTheSame " + result);
return result;
}
@Override
public boolean areContentsTheSame(@NonNull MultiItemBean oldItem, @NonNull MultiItemBean newItem) {
boolean result = Objects.equals(oldItem,newItem);
Log.d(TAG, "areContentsTheSame " + result);
return result;
}
@Nullable
@Override
public Object getChangePayload(@NonNull MultiItemBean oldItem, @NonNull MultiItemBean newItem) {
boolean updateProgress = oldItem.getOne()!= null && newItem.getOne() != null
&& oldItem.getOne().getProgress() != newItem.getOne().getProgress();
if(updateProgress){
Bundle data = new Bundle();
data.putInt(KEY_PROGRESS,newItem.getOne().getProgress());
return data;
}
return super.getChangePayload(oldItem, newItem);
}
});
}
public AsyncListDiffer<MultiItemBean> getDiffer() {
return mDiffer;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_ONE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_one, parent, false);
return new OneViewHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_two, parent, false);
return new TwoViewHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
if(payloads == null || payloads.isEmpty() || payloads.get(0) == null){
super.onBindViewHolder(holder,position,payloads);
}else{
if(getItemViewType(position) == TYPE_ONE){
Bundle data = (Bundle) payloads.get(0);
OneViewHolder oneViewHolder = (OneViewHolder) holder;
int progress = data.getInt(KEY_PROGRESS,0);
if(progress != 0){
oneViewHolder.progressTv.setText(String.valueOf(progress));
oneViewHolder.progressBar.setProgress(progress);
}
}
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Log.d(TAG,"onBindViewHolder");
int viewType = getItemViewType(position);
MultiItemBean itemBean = mDiffer.getCurrentList().get(position);
if (viewType == TYPE_ONE) {
OneViewHolder one = (OneViewHolder) holder;
one.nameTv.setText(itemBean.getOne().getName());
one.progressTv.setText("" + itemBean.getOne().getProgress());
one.progressBar.setProgress(itemBean.getOne().getProgress());
} else {
TwoViewHolder two = (TwoViewHolder) holder;
two.nameTv.setText(itemBean.getTwo().getName());
two.detailTv.setText(itemBean.getTwo().getDetail());
}
}
@Override
public int getItemViewType(int position) {
return mDiffer.getCurrentList().get(position).getStatus();
}
@Override
public int getItemCount() {
return mDiffer.getCurrentList().size();
}
static class OneViewHolder extends RecyclerView.ViewHolder {
TextView nameTv;
TextView progressTv;
ProgressBar progressBar;
public OneViewHolder(@NonNull View itemView) {
super(itemView);
nameTv = itemView.findViewById(R.id.tv_name);
progressTv = itemView.findViewById(R.id.tv_progress);
progressBar = itemView.findViewById(R.id.progressBar);
}
}
static class TwoViewHolder extends RecyclerView.ViewHolder {
TextView nameTv;
TextView detailTv;
public TwoViewHolder(@NonNull View itemView) {
super(itemView);
nameTv = itemView.findViewById(R.id.tv_name);
detailTv = itemView.findViewById(R.id.tv_detail);
}
}
}