Android RecyclerView DiffUtilローカルリフレッシュピットパッケージ

74082 ワード

最近少し暇があって最近使ったDiffUtilの局部のリフレッシュを1つの整理を行って1つのBaseDiffAdapterをカプセル化して、1つのクラスはいくつかの穴を完成して基本的に踏んでしまって、どんなピクチャーのきらめき、itemのきらめき、データソースのリフレッシュviewが更新しないなど
コードを置いてレンガを撮るのを歓迎します
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();
        }
    }

ソースリンク