Лучший подход для использования DiffUtil с LIveData + Room Database? - PullRequest
0 голосов
/ 25 февраля 2019

Я использую Room Database с LiveData, но моя локальная база данных обновляется слишком быстро в соответствии с нашими требованиями, и в то же время мне приходится перезагружать мое представление о переработчике. Вместо вызова notifyDataSetChanged() для адаптера, япопытка использовать DiffUtil, но происходит сбой или перезагрузка неправильно, это неясно.Я следую этому уроку: Учебники Ссылка здесь

MyAdapter:

public class SwitchGridAdapter extends RecyclerView.Adapter<SwitchGridAdapter.ViewHolder> {


    private  List<Object> allItemsList;

    private LayoutInflater mInflater;
    private OnItemClickListener mClickListener;
    private  Context context;

    private Queue<List<Object>> pendingUpdates =
            new ArrayDeque<>();

    // data is passed into the constructor
  public SwitchGridAdapter(Context context,List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList) {
        this.mInflater = LayoutInflater.from(context);
         this.context = context;

       allItemsList = new ArrayList<>();
        if (applianceList!=null) allItemsList.addAll(applianceList);
        if (zmoteRemoteList!=null)allItemsList.addAll(zmoteRemoteList);

    }

    // inflates the cell layout from xml when needed
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R .layout.switch_grid_item, parent, false);

        return new ViewHolder(view);
    }


    // binds the data to the textview in each cell
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
     // Doing some update with UI Elements
    }

    // total number of cells
    @Override
    public int getItemCount() {
        return allItemsList.size();
    }

    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener {
        TextView myTextView;
        ImageView imgSwitch;

        ViewHolder(View itemView) {
            super(itemView);
            myTextView = (TextView) itemView.findViewById(R.id.txtSwitchName);
            imgSwitch = (ImageView) itemView.findViewById(R.id.imgSwitchStatus);

            itemView.setOnClickListener(this);

            itemView.setOnLongClickListener(this);

        }

        @Override
        public void onClick(View view) {
           // handling click 
        }

        @Override
        public boolean onLongClick(View view) {
           return true;
    }

    // convenience method for getting data at click position
    Object getItem(int id) {
        return allItemsList.get(id);
    }

    // allows clicks events to be caught
   public void setClickListener(OnItemClickListener itemClickListener) {
        this.mClickListener = itemClickListener;
    }

    // parent activity will implement this method to respond to click events
    public interface OnItemClickListener {
        void onItemClick(View view, int position);
        void onItemLongPressListner(View view, int position);
    }



// ✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
// From This Line Reloading with Diff Util is Done .
//✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅


    public  void  setApplianceList( List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList)
    {

        if (allItemsList == null)
            allItemsList = new ArrayList<>();

        List<Object> newAppliances = new ArrayList<>();
        if (applianceList!=null) newAppliances.addAll(applianceList);

        updateItems(newAppliances);

    }


    // when new data becomes available
    public void updateItems(final List<Object> newItems) {
        pendingUpdates.add(newItems);
        if (pendingUpdates.size() > 1) {
            return;
        }
        updateItemsInternal(newItems);
    }
    // This method does the heavy lifting of
    // pushing the work to the background thread
    void updateItemsInternal(final List<Object> newItems) {
        final List<Object> oldItems = new ArrayList<>(this.allItemsList);
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                final DiffUtil.DiffResult diffResult =
                        DiffUtil.calculateDiff(new DiffUtilHelper(oldItems, newItems));
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        applyDiffResult(newItems, diffResult);
                    }
                });
            }
        }).start();
    }
    // This method is called when the background work is done
    protected void applyDiffResult(List<Object> newItems,
                                   DiffUtil.DiffResult diffResult) {
        dispatchUpdates(newItems, diffResult);
    }
    // This method does the work of actually updating
    // the backing data and notifying the adapter
    protected void dispatchUpdates(List<Object> newItems,
                                   DiffUtil.DiffResult diffResult) {


            // ❌❌❌❌❌❌ Next Line is Crashing the app ❌❌❌❌❌
            pendingUpdates.remove();

            dispatchUpdates(newItems, diffResult);
            if (pendingUpdates.size() > 0) {
                updateItemsInternal(pendingUpdates.peek());
            }
    }

}

Наблюдение LiveData

 public  void setUpAppliancesListLiveData()
    {

        if (applianceObserver!=null)
        {
            applianceObserver  = null;
        }


        Log.e("Appliance Fetch","RoomName:"+this.roomName);

      applianceObserver =  new Observer<List<Appliance>>() {
            @Override
            public void onChanged(@Nullable List<Appliance> applianceEntities) {
                // Log.e("Appliance Result","Appliance List \n\n:"+applianceEntities.toString());

                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        List<Appliance> applianceListTemp =  applianceEntities;

                        zmoteRemoteList =  new ArrayList<>();  //appDelegate.getDatabase().zmoteRemoteDao().getRemoteList(roomName);

                        // Sort according to name

                        Collections.sort(applianceListTemp, new Comparator<Appliance>() {
                            @Override
                            public int compare(Appliance item, Appliance t1) {
                                String s1 = item.getSwitchName();
                                String s2 = t1.getSwitchName();
                                return s1.compareToIgnoreCase(s2);
                            }

                        });


                        if(getActivity()!=null) {
                            getActivity().runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    applianceList = applianceListTemp;
                                    mRecyclerView.getRecycledViewPool().clear();
                                    adapter.setApplianceList(applianceList,zmoteRemoteList);
                                }
                            });

                        }

                    }
                }).start();
            }
        };



        appDelegate.getDatabase().applianceDao().getApplinaceListByRoomName(this.roomName).observe(this, applianceObserver);

    }
...