【问题标题】:Update RecyclerView with DiffUtil and AsyncListDiffer not Working使用 DiffUtil 和 AsyncListDiffer 更新 RecyclerView 不起作用
【发布时间】:2021-02-24 10:07:53
【问题描述】:

我正在使用DiffUtilAsyncListDifferFragment 中创建RecyclerView,因为我不想使用notifyDataSetChanged() 方法。但是我在使用这种方法时遇到了一个问题。我正在尝试从数据库中检索项目,但每次数据更改(增加)时,UI 都不会直接更新。我必须先关闭我的应用,然后再打开它,或者去另一个班级检查更新的项目。

这是我的适配器:

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;
    }
 }

我不知道为什么它不起作用,因为我之前尝试过使用DiffUtilAsyncListDiffer 并且没有问题。任何帮助或建议都会很棒。提前致谢。

【问题讨论】:

    标签: android android-recyclerview android-diffutils android-asynclistdiffer


    【解决方案1】:

    据我从您的代码中看到的,您可能误用了DiffUtil.ItemCallbackareItemsTheSame(int oldItemPosition, int newItemPosition) 的目的是两个决定,无论两个对象代表同一个项目,但在您的代码中,您使用的是 .equals 方法,即 content comparison。 在areItemsTheSame 中,您应该检查项目id 相等性,因为您没有ID,您可以简单地使用ticker 字符串进行检查,但请注意,如果两个项目具有相同的@ 987654327@这两个项目将匹配:

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

    不同的是,areContentsTheSame 检查两个项目是否具有相同的数据,并且仅当 areItemsTheSame 返回 true 时才调用此方法。在这里,您可能应该检查旧项目和新项目之间的类属性是否匹配,例如:

    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))
    }
    

    【讨论】:

    • 我已经尝试了你的建议,但它仍然不起作用,就你从我的代码中看到的,我的片段中是否做错了什么?
    • 从问题中的代码很难说,要不要分享一个repo?
    【解决方案2】:

    您需要执行此步骤。花了很长时间后,我发现这是因为空列表。更新列表时这样做::

    fun updateList(updatedList: List<Notification>) {
        if (updatedList.isEmpty()) {
            differ.submitList(emptyList())
            return
        }
        differ.submitList(updatedList)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-04
      • 2018-03-17
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 2022-08-21
      • 2023-01-24
      相关资源
      最近更新 更多