Android RecyclerView DiffUtilローカルリフレッシュピットパッケージ
74082 ワード
最近少し暇があって最近使ったDiffUtilの局部のリフレッシュを1つの整理を行って1つのBaseDiffAdapterをカプセル化して、1つのクラスはいくつかの穴を完成して基本的に踏んでしまって、どんなピクチャーのきらめき、itemのきらめき、データソースのリフレッシュviewが更新しないなど
コードを置いてレンガを撮るのを歓迎します
使用:BaseDiffBeanを実装するエンティティクラスを先に書きます
更にadapterを書いてBaseDiffAdapterを継承します
ソースリンク
コードを置いてレンガを撮るのを歓迎します
package com.example.basediffadapter;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
/**
* Diff Adapter
* List notifyDataSetChanged()
* setData addData removeData getData updateData
* Project: ProjectBaseDiffAdapter
* Author: LiShen
* Time: 2018/9/11 15:16
*/
public abstract class BaseDiffAdapter<T extends BaseDiffBean, V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V> {
private Activity activity;
private Class<T> tClass;
private Handler mainHandler = new Handler(Looper.getMainLooper());
private List<T> oldData = new ArrayList<>();//
private List<T> data = new ArrayList<>();//
private OnItemClickListener<T> onItemClickListener;
private boolean canNotRefresh = false;
public BaseDiffAdapter(Activity activity, Class<T> tClass) {
this.activity = activity;
this.tClass = tClass;
}
/**
*
*
* @param holder
* @param position
*/
public abstract void bindViewAndData(V holder, int position);
/**
*
*
* @param holder
* @param position
* @param newBean
*/
public abstract void partBindViewAndData(V holder, int position, T newBean);
@Override
public abstract V onCreateViewHolder(ViewGroup parent, int viewType);
@Override
public final void onBindViewHolder(V holder, int position) {
bindViewAndData(holder, position);
}
@Override
public final void onBindViewHolder(@NonNull V holder, int position, @NonNull List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
partBindViewAndData(holder, position, (T) payloads.get(0));
}
}
@Override
public int getItemCount() {
return data.size();
}
public void setData(List<T> outData) {
setData(outData, null);
}
/**
* data oldData
* DiffUtil ( ) dispatchUpdatesTo
* adapter ( ) data
* oldData ( )
*
*
* @param outData
* @param callback
*/
public void setData(List<T> outData, final OnSetDataFinishCallback callback) {
if (canNotRefresh) {
return;
}
canNotRefresh = true;
data.clear();
if (outData != null) {
data.addAll(outData);
}
WorkThreadHelper.get().execute(new Runnable() {
@Override
public void run() {
//
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(
new BaseDiffCallback(
new ArrayList<>(oldData),
new ArrayList<>(data)));
mainHandler.post(new Runnable() {
@Override
public void run() {
// dispatch adapter
result.dispatchUpdatesTo(BaseDiffAdapter.this);
}
});
oldData.clear();
for (T t : data) {
//
oldData.add(JSON.parseObject(JSON.toJSONString(t), tClass));
}
canNotRefresh = false;
//
if (callback != null) {
mainHandler.post(new Runnable() {
@Override
public void run() {
callback.onFinish();
}
});
}
}
});
}
/**
*
*
* @param t
*/
public void addData(T t) {
if (t != null) {
List<T> temp = new ArrayList<>(data);
temp.add(t);
setData(temp);
}
}
/**
*
*
* @param index
* @param t
*/
public void addData(int index, T t) {
if (t != null) {
List<T> temp = new ArrayList<>(data);
temp.add(index, t);
setData(temp);
}
}
/**
*
*
* @param list
*/
public void addData(List<T> list) {
if (list != null) {
List<T> temp = new ArrayList<>(data);
temp.addAll(list);
setData(temp);
}
}
/**
*
*
* @param position
*/
public void removeData(int position) {
List<T> temp = new ArrayList<>(data);
temp.remove(position);
setData(temp);
}
/**
*
*
* @param id
*/
public void removeData(String id) {
int flag = -1;
for (int i = 0; i < data.size(); i++) {
if (data.get(i).getDiffId().equals(id)) {
flag = i;
break;
}
}
if (flag >= 0) {
removeData(flag);
}
}
/**
*
*
* @param t
*/
public void removeData(T t) {
List<T> temp = new ArrayList<>(data);
temp.remove(t);
setData(temp);
}
/**
*
*/
public void clearData() {
List<T> temp = new ArrayList<>(data);
temp.clear();
setData(temp);
}
/**
* {@link #data}
*/
public void notifyDataUpdated() {
setData(new ArrayList<>(getData()));
}
public List<T> getData() {
return data;
}
public T getItemData(int position) {
return data.get(position);
}
public View inflater(@LayoutRes int layoutId) {
return getActivity().getLayoutInflater().inflate(layoutId, null);
}
public Activity getActivity() {
return activity;
}
/**
* Item
*
* @param holder
* @return
*/
public int onViewHolderItemClick(RecyclerView.ViewHolder holder) {
int position = holder.getLayoutPosition();
if (position >= 0 && position < getData().size()) {
if (getOnItemClickListener() != null) {
getOnItemClickListener().onItemClick(position, getItemData(position));
}
}
return position;
}
public interface OnItemClickListener<T> {
void onItemClick(int position, T t);
}
public void setOnItemClickListener(OnItemClickListener<T> onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public OnItemClickListener<T> getOnItemClickListener() {
return onItemClickListener;
}
private class BaseDiffCallback extends DiffUtil.Callback {
private List<T> oldList;
private List<T> newList;
private BaseDiffCallback(List<T> oldList, List<T> newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList != null ? oldList.size() : 0;
}
@Override
public int getNewListSize() {
return newList != null ? newList.size() : 0;
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getDiffId().equals(
newList.get(newItemPosition).getDiffId());
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getDiffContent().equals(
newList.get(newItemPosition).getDiffContent());
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
T newBean = newList.get(newItemPosition);
if (!areContentsTheSame(oldItemPosition, newItemPosition)) {
return newBean;
}
return null;
}
}
public interface OnSetDataFinishCallback {
void onFinish();
}
}
使用:BaseDiffBeanを実装するエンティティクラスを先に書きます
public class DemoBean implements BaseDiffBean, Comparable<DemoBean> {
public int id;
@DrawableRes
public int icon;
public String content;
public void generateData() {
//
id = DemoUtil.generateId();
icon = DemoUtil.generateRandomIcon();
content = DemoUtil.generateRandomString();
}
/**
*
**/
@NonNull
@Override
public String getDiffContent() {
return "DemoBean{" +
"id=" + id +
", icon=" + icon +
", content='" + content + '\'' +
'}';
}
/**
*
**/
@NonNull
@Override
public String getDiffId() {
return String.valueOf(id);
}
//
@Override
public int compareTo(DemoBean o) {
return (int) (this.id - o.id);
}
}
更にadapterを書いてBaseDiffAdapterを継承します
public class DemoAdapter extends BaseDiffAdapter<DemoBean, DemoAdapter.ViewHolder> {
public DemoAdapter(Activity activity, Class<DemoBean> demoBeanClass) {
super(activity, demoBeanClass);
setHasStableIds(true);
}
@Override
public void bindViewAndData(final ViewHolder holder, int position) {
Log.i("BaseDiffAdapter", "bindViewAndData: " + position);
//
DemoBean data = getItemData(position);
// setHasStableIds getItemId
Integer cache = (Integer) holder.ivItemDemo.getTag(R.id.ivItemDemo);
if (cache == null || cache != data.icon) {
holder.ivItemDemo.setImageResource(data.icon);
holder.ivItemDemo.setTag(R.id.ivItemDemo, data.icon);
}
holder.tvItemDemo.setText(data.content);
holder.tvItemDemoId.setText("ID: " + data.id);
holder.ivItemDemoDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int index = holder.getAdapterPosition();
removeData(index);//
}
});
}
@Override
public void partBindViewAndData(ViewHolder holder, int position, DemoBean newBean) {
Log.d("BaseDiffAdapter", "partBindViewAndData: " + position);
//
Integer cache = (Integer) holder.ivItemDemo.getTag(R.id.ivItemDemo);
if (cache == null || cache != newBean.icon) {
holder.ivItemDemo.setImageResource(newBean.icon);
holder.ivItemDemo.setTag(R.id.ivItemDemo, newBean.icon);
}
holder.tvItemDemo.setText(newBean.content);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(inflater(R.layout.item_demo));
}
@Override
public long getItemId(int position) {
return getItemData(position).id;
}
class ViewHolder extends RecyclerView.ViewHolder {
private ImageView ivItemDemo;
private ImageView ivItemDemoDelete;
private TextView tvItemDemo;
private TextView tvItemDemoId;
ViewHolder(@NonNull View itemView) {
super(itemView);
ivItemDemo = itemView.findViewById(R.id.ivItemDemo);
ivItemDemoDelete = itemView.findViewById(R.id.ivItemDemoDelete);
tvItemDemo = itemView.findViewById(R.id.tvItemDemo);
tvItemDemoId = itemView.findViewById(R.id.tvItemDemoId);
}
}
}
/**
*
*/
private void addData() {
DemoBean d = new DemoBean();
d.generateData();
demoAdapter.addData(0, d);//
// demoAdapter.addData(d);//
//
mainHandler.postDelayed(new Runnable() {
@Override
public void run() {
RecyclerView rvDemo = findViewById(R.id.rvDemo);
rvDemo.smoothScrollToPosition(0);
}
}, 100);
}
/**
* item
*/
private void refreshData() {
int max = demoAdapter.getItemCount();
if (max > 0) {
Random random = new Random();
int chosen = random.nextInt(max - 1);
//
DemoBean itemData = demoAdapter.getItemData(chosen);
itemData.content = DemoUtil.generateRandomString();
itemData.icon = DemoUtil.generateRandomIcon();
// ! notifyDataSetChanged
demoAdapter.notifyDataUpdated();
}
}
ソースリンク