I'm creating a RecyclerView in Fragmentusing DiffUtil and AsyncListDiffer because I don't want to use notifyDataSetChanged() method. But I'm facing a problem while using this approach. I'm trying to retrieve items from the database, but every time the data changes (increase) the UI won't update directly. I have to close my app first and then open it again or go to another class to check the updated item.
This is my adapter:
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);
}
Code in Fragment:
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 );
}
My model:
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;
}
}
I don't know why it's not working because I have tried using DiffUtil and AsyncListDiffer before and there is no problem. Any helps or suggestions would be great. Thanks in advance.
As far as I see from your code, you're probably misusing
DiffUtil.ItemCallback. The purpose ofareItemsTheSame(int oldItemPosition, int newItemPosition)is two decide wheather two object represent the same item but in your code you're using.equalsmethod, that is for content comparison. WithinareItemsTheSameyou should check items id equality, since you don't have ids, you could simply do the check by usingtickerstring, but be aware that if two items have the sametickerthe two items will match:Differently,
areContentsTheSamechecks whether two items have the same data and this method is called only ifareItemsTheSamereturns true. In here, you should probably check if class properties matches between the old and the new item, something like:Be aware that
areContentsTheSamebusiness logic it's up to you, accordingly to the properties you identified to be part of the content. The standard approach is to use.equals()method, but doesn't seem to be your case.