Обновите RecyclerView, если DiffUtil и AsyncListDiffer не работают

Я создаю RecyclerView в Fragmentиспользуя и потому что я не хочу использовать notifyDataSetChanged()метод. Но я столкнулся с проблемой при использовании этого подхода. Я пытаюсь получить элементы из базы данных, но каждый раз, когда данные изменяются (увеличиваются), пользовательский интерфейс не обновляется напрямую. Мне нужно сначала закрыть свое приложение, а затем открыть его снова или перейти в другой класс, чтобы проверить обновленный элемент.

Это мой адаптер:

      public class AdapterSaham extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements SectionIndexer, SearchFilter {
   public static final int SECTION_VIEW = 0;
   public static final int CONTENT_VIEW = 1;

   List<DaftarSaham> daftarSahamList;
   private ArrayList<Integer> mSectionPositions;
   private static int  lastClicked = -1;
   WeakReference<Context> mContextWeakReference;
   private ItemClickListener itemClickListener;
   private int lastPosition = -1;
   int row_index = -1;

   public AdapterSaham(ArrayList<DaftarSaham> daftarSaham, Context context, ItemClickListener clickListener){
       this.daftarSahamList = daftarSaham;
       this.mContextWeakReference = new WeakReference<Context> ( context );
       this.itemClickListener = clickListener;
   }

   private static final DiffUtil.ItemCallback<DaftarSaham> DIFF_CALLBACK = new DiffUtil.ItemCallback<DaftarSaham> () {
       @Override
       public boolean areItemsTheSame(@NonNull DaftarSaham oldItem, @NonNull DaftarSaham newItem) {
           return newItem.getTicker ().equals ( oldItem.getTicker () ) && newItem.getCompanyName ().equals ( newItem.getCompanyName () );
       }

       @SuppressLint("DiffUtilEquals")
       @Override
       public boolean areContentsTheSame(@NonNull DaftarSaham oldItem, @NonNull DaftarSaham newItem) {
           return newItem.equals ( oldItem );
       }

   };

   private  AsyncListDiffer<DaftarSaham> differ = new AsyncListDiffer<DaftarSaham> (this, DIFF_CALLBACK  );

   @NonNull
   @Override
   public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

       Context ctx = mContextWeakReference.get ();
       View view = LayoutInflater.from ( parent.getContext () ).inflate ( R.layout.list_item,parent,false  );
      
   
      return new ItemViewHolder ( view, ctx , itemClickListener);

   }

   @Override
   public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
       Context ctx = mContextWeakReference.get ();
       if (ctx == null){
           return;
       }
      
       ItemViewHolder itemViewHolder= (ItemViewHolder) holder;
       DaftarSaham daftarSaham =  differ.getCurrentList ().get ( position);
       itemViewHolder.txtTickerSaham.setText ( daftarSaham.getTicker () );
       itemViewHolder.txtCompanyName.setText ( daftarSaham.getCompanyName () );
   }

   public class ItemViewHolder extends RecyclerView.ViewHolder {
       private TextView txtTickerSaham, txtCompanyName;
       private LinearLayout cardView;

       ItemClickListener itemClickListener;

       public ItemViewHolder(@NonNull View itemView, final Context context, ItemClickListener itemClickListener) {
           super ( itemView );
           txtTickerSaham = (TextView) itemView.findViewById ( R.id.tickerSaham );
           txtCompanyName = (TextView) itemView.findViewById ( R.id.tv_company_name );
           cardView = (LinearLayout) itemView.findViewById ( R.id.cvRecycler );

           this.itemClickListener = itemClickListener;

       }

   }

  @Override
   public int getItemCount() {

       return differ.getCurrentList ().size ();
   }

   public void submitList(List<DaftarSaham> newdataList){
       differ.submitList ( newdataList );
       daftarSahamList = new ArrayList<> (newdataList);
   }

Код во фрагменте:

       ViewGroup.LayoutParams params=recyclerViewIndexer.getLayoutParams();
        params.height= h;
        recyclerViewIndexer.setLayoutParams(params);
        recyclerViewIndexer.setHasFixedSize ( true );
        recyclerViewIndexer.setLayoutManager ( new LinearLayoutManager ( getContext ()) );

 StringRequest stringRequest = new StringRequest ( Request.Method.GET, URL,
               new Response.Listener<String> () {
                   @Override
                   public void onResponse(String response) {
                       ArrayList<HashMap<String,String>> list = new ArrayList<> ();
                       try {
                           JSONObject jsonObject = new JSONObject (response);
                           JSONArray jsonArray = jsonObject.getJSONArray ( "data_emiten" );
                           for(int i = 0; i < jsonArray.length (); i++){
                               JSONObject jo = jsonArray.getJSONObject ( i );
                               String ticker = jo.getString ( "ticker" );
                               String companyName = jo.getString ( "companyName" );
                               daftarNonSection.add ( new DaftarSaham (ticker, companyName, false) );

                           }

                       } catch (JSONException e) {
                           e.printStackTrace ();
                       }

                       getHeaderListLetter ( daftarSahamList,daftarNonSection );
                       adapterSaham = new AdapterSaham ( daftarSahamList, getContext (), new AdapterSaham.ItemClickListener () {
                           @Override
                           public void onItemClick(Integer numbers, boolean isSelected) {
                               String ticker = "";
                               if (isSelected ){
                                   ticker = daftarSahamList.get ( Integer.valueOf ( numbers) ).ticker;
                               }
                               SlidingTab slidingTab = (SlidingTab) getActivity ();
                               slidingTab.setTicker (ticker);
                           }
                       } );
                       recyclerViewIndexer.setAdapter ( adapterSaham );
                       adapterSaham.submitList ( daftarSahamList );
                       Log.d ( "TAG", "onResponse: "+ response );
                   }
               },
               new Response.ErrorListener () {
                   @Override
                   public void onErrorResponse(VolleyError error) {
                       Log.d ( "TAG", "onErrorResponse: "+error );
                   }
               } );

       int socketTimeOut = 50000;
       RetryPolicy policy = new DefaultRetryPolicy (socketTimeOut, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
       stringRequest.setRetryPolicy ( policy );
       RequestQueue requestQueue = Volley.newRequestQueue ( getContext () );
       requestQueue.add ( stringRequest );
   }

Моя модель:

      public class DaftarSaham implements Comparable<DaftarSaham> {

    public String ticker;
    public String companyName;
    public boolean isSection;
    private boolean isSelected = false;

    public DaftarSaham() {

    }

    public DaftarSaham(String ticker, String companyName, boolean isSection) {
        this.ticker = ticker;
        this.companyName = companyName;
        this.isSection = isSection;
    }

    public String getCompanyName() {
        return companyName;
    }
    public void setTicker(String ticker) {
        this.ticker = ticker;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }


    public String getTicker() {
        return ticker;
    }
 }

Я не знаю, почему это не работает, потому что я пробовал использовать DiffUtil и AsyncListDifferраньше и проблем нет. Любая помощь или предложения были бы замечательными. Заранее спасибо.

2 ответа

Насколько я понимаю из вашего кода, вы, вероятно, неправильно используете DiffUtil.ItemCallback. Цель areItemsTheSame(int oldItemPosition, int newItemPosition) два решают, представляют ли два объекта один и тот же элемент, но в вашем коде вы используете .equalsметод, то есть для сравнения контента. Внутри вы должны проверить равенство идентификаторов элементов , поскольку у вас нет идентификаторов, вы можете просто выполнить проверку, используя строку, но имейте в виду, что если два элемента имеют одинаковые ticker два элемента будут соответствовать:

      public boolean areItemsTheSame(@NonNull DaftarSaham oldItem, @NonNull DaftarSaham newItem) {
       return newItem.getTicker() == oldItem.getTicker()
}

По-другому проверяет, имеют ли два элемента одинаковые данные, и этот метод вызывается только в том случае, если areItemsTheSameвозвращает истину. Здесь вы, вероятно, должны проверить, совпадают ли свойства класса между старым и новым элементом, например:

      public boolean areContentsTheSame(@NonNull DaftarSaham oldItem, @NonNull DaftarSaham newItem) {
   return (newItem.getTicker() == oldItem.getTicker()) && (newItem.getCompanyName() == oldItem.getCompayName())
}

Быть в курсе, что areContentsTheSameбизнес-логика зависит от вас, в зависимости от свойств, которые вы определили как часть содержимого. Стандартный подход - использовать .equals() метод, но, похоже, не в вашем случае.

      public boolean areContentsTheSame(@NonNull DaftarSaham oldItem, @NonNull DaftarSaham newItem) {
   return (newItem.equals(oldItem))
}

Вам нужно сделать этот шаг. Потратив много времени, я обнаружил, что это из-за пустого списка. При обновлении списка сделайте следующее:

      fun updateList(updatedList: List<Notification>) {
    if (updatedList.isEmpty()) {
        differ.submitList(emptyList())
        return
    }
    differ.submitList(updatedList)
}
Другие вопросы по тегам