Why Recyclerview adapter onBindViewHolder is called more than once? - android

I use this tutorial to implement DiffUtil in my recyclerview. My aim is to add single item to the bottom of the recyclerview without reloading the rest of the recyclerview. I used firestore addSnapshotListener to call the adapter. The problem is the onBindViewHolder is called multiple times (ie, no of items present in the list). I dont think that is suppose to happen when using DiffUtil, right? It should only call onBindViewHolder for the item that is added to recyclerview, right?
This is the code whre I call the adapter:
#Override
protected void onStart()
{
super.onStart();
reference
.addSnapshotListener((Activity)context, new EventListener<QuerySnapshot>()
{
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots,
#Nullable FirebaseFirestoreException e)
{
if (e != null)
{
Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
return;
}
CommentsListAdapter adapter = new CommentsListAdapter(context);
commentsRecyclerView.setAdapter(adapter);
comments = new ArrayList<>();
for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots)
{
Comment comment = snapshot.toObject(Comment.class).withId(snapshot.getId());
comments.add(comment);
}
adapter.submitList(comments);
commentsRecyclerView.smoothScrollToPosition(adapter.getItemCount());
}
});
}
This is the adapter class:
class CommentsListAdapter extends ListAdapter<Comment, CommentsListAdapter.CommentsViewHolder>
{
private Context context;
protected CommentsListAdapter(Context context)
{
super(DIFF_CALLBACK);
this.context = context;
}
private static final DiffUtil.ItemCallback<Comment> DIFF_CALLBACK = new DiffUtil.ItemCallback<Comment>()
{
#Override
public boolean areItemsTheSame(#NonNull Comment oldItem, #NonNull Comment newItem)
{
return oldItem.commentId.equals(newItem.commentId);
}
#Override
public boolean areContentsTheSame(#NonNull Comment oldItem, #NonNull Comment newItem)
{
return oldItem.commentId.equals(newItem.commentId);
}
};
#NonNull
#Override
public CommentsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.from(context)
.inflate(R.layout.comment_list_item, parent, false);
return new CommentsViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final CommentsViewHolder holder, int position)
{
System.out.println("POSITION: " + position);
holder.commentText.setText(getItem(position).getComment());
holder.timeText.setText(getItem(position).getCommentDateCreated());
}
public class CommentsViewHolder extends RecyclerView.ViewHolder
{
private TextView commentText;
private TextView timeText;
public CommentsViewHolder(#NonNull View itemView)
{
super(itemView);
commentText = itemView.findViewById(R.id.commentText);
timeText = itemView.findViewById(R.id.timeText);
}
}
}
I am new to DiffUtil. So, is it suppose to happen ? Or Is there anything wrong with the code?

Every time when you get callback from Firestore you recreate your CommentsListAdapter
Pull the adapter into the global variable in your Activity and call only adapter.submitList(comments); in Firestore callback
Your Edited code:
CommentsListAdapter adapter = new CommentsListAdapter(context);
#Override
protected void onStart()
{
super.onStart();
commentsRecyclerView.setAdapter(adapter);
reference
.addSnapshotListener((Activity)context, new EventListener<QuerySnapshot>()
{
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots,
#Nullable FirebaseFirestoreException e)
{
if (e != null)
{
Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
return;
}
comments = new ArrayList<>();
for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots)
{
Comment comment = snapshot.toObject(Comment.class).withId(snapshot.getId());
comments.add(comment);
}
adapter.submitList(comments);
commentsRecyclerView.smoothScrollToPosition(adapter.getItemCount());
}
});
}

Related

Getting a list inside a firestore document into a recyclerview

i have a document inside firestore, that document also has a list inside is called "foods". I want to be able to load only that list of "foods" into a recyclerview, I'm not sure how to query the list for recycler options. Here is what the DB structure looks like:
Here is my Adapter
List<Order> myOrders;
public OrderDetailAdapter(#NonNull FirestoreRecyclerOptions<Order> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull OrderDetailAdapter.DetailsHolder holder, int position, #NonNull Order model) {
Order order = myOrders.get(position);
holder.product_name.setText(model.getProductName());
holder.product_price.setText(model.getPrice());
holder.product_quantity.setText(model.getQuantity());
holder.product_discount.setText(model.getDiscount());
}
#NonNull
#Override
public OrderDetailAdapter.DetailsHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.order_item_layout, parent,false);
return new DetailsHolder(v);
}
public class DetailsHolder extends RecyclerView.ViewHolder {
TextView product_name, product_price, product_discount, product_quantity;
public DetailsHolder(#NonNull View itemView) {
super(itemView);
product_name = itemView.findViewById(R.id.product_name);
product_price = itemView.findViewById(R.id.product_price);
product_discount = itemView.findViewById(R.id.product_discount);
product_quantity = itemView.findViewById(R.id.product_quantity);
}
}
#Override
public int getItemCount() {
return myOrders.size();
}
}
Here is my Activity:
private FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference documentReference;
TextView order_id, order_comment, order_date, order_total;
String order_id_value ="";
RecyclerView lstFoods;
RecyclerView.LayoutManager layoutManager;
OrderDetailAdapter orderAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_details);
if (getIntent() !=null)
order_id_value = getIntent().getStringExtra("order_number");
documentReference = db.collection("Requests").document(order_id_value);
lstFoods = findViewById(R.id.food_list);
lstFoods.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
lstFoods.setLayoutManager(layoutManager);
order_id.setText(order_id_value);
documentReference.addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot documentSnapshot, #Nullable FirebaseFirestoreException e) {
if (documentSnapshot.exists()){
Order order = documentSnapshot.toObject(Order.class);
orderAdapter.notifyDataSetChanged();
lstFoods.setAdapter(orderAdapter);
}else{
Log.d("TAG", "ERROR");
}
}
});
}
#Override
protected void onStart() {
super.onStart();
orderAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
orderAdapter.stopListening();
}
}
When i try to run it i get the following error:
error: incompatible types: List cannot be converted to FirestoreRecyclerOptions
super(options);

Recyclerview fetch existing data after delete an item from adapter and does not update properly

I try to implement a friend request feature in the fragment using custom adapter with firebase database. The problem is when a user accepts or delete someone request, it deletes from firebase but not properly update in the RecyclerView. this problems occurred in only runtime. If I refresh the page then my problem goes away.
Let I have two friend request. If I delete 2nd data then 2nd data will gone from RecyclerView but the problem is RecyclerView shows 1st data doubles. and if I delete 1st data then 1st data goes in the 2nd row and 2nd data came into the first row.
here is my database screenshot
Fragment class-
public class NotificationFragment extends Fragment {
private RecyclerView NotificationRecyclerView;
private NotificationAdapter adapter;
private List<Friend> friendList;
public NotificationFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_notification, container, false);
NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
NotificationRecyclerView.setHasFixedSize(true);
LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
NotificationRecyclerView.setLayoutManager(LayoutManager);
friendList = new ArrayList<>();
adapter = new NotificationAdapter(getContext(), friendList);
NotificationRecyclerView.setAdapter(adapter);
readAllNotification();
return view;
}
private void readAllNotification() {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Friend friend = snapshot.getValue(Friend.class);
if (firebaseUser.getUid().equals(friend.getReceiverID())) {
friendList.add(friend);
}
}
Collections.reverse(friendList);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Custom Adapter -
public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder> {
private Context context;
private List<Friend> friendList;
public NotificationAdapter(Context context, List<Friend> friendList) {
this.context = context;
this.friendList = friendList;
}
#NonNull
#Override
public NotificationViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.single_notification_item, parent, false);
return new NotificationAdapter.NotificationViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position) {
final Friend friend = friendList.get(position);
getUserInfo(holder.profileImage, holder.NotificationUserName, friend.getSenderID());
holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase.getInstance().getReference("FriendRequest")
.child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
removeItem(position);
Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
}
});
}
});
}
public void removeItem(int position) {
friendList.remove(position);
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return friendList.size();
}
private void getUserInfo(final CircleImageView prfileImage, final TextView NotificationUserName, String senderID) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(senderID);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Users users = dataSnapshot.getValue(Users.class);
NotificationUserName.setText(users.getUserName());
Picasso.with(context).load(users.getImageUrl()).into(prfileImage);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public class NotificationViewHolder extends RecyclerView.ViewHolder {
private TextView NotificationUserName;
private Button cancelRequestButton;
private CircleImageView profileImage;
public NotificationViewHolder(#NonNull View itemView) {
super(itemView);
NotificationUserName = itemView.findViewById(R.id.NotificationUserName);
cancelRequestButton = itemView.findViewById(R.id.cancelRequestBtn);
profileImage = itemView.findViewById(R.id.profileImage);
}
}
}
My APP Problems screenshot -
let I have two request
1) if I delete 2nd data 1st data show doubles:
2) if I delete 1st data, 1st data goes into 2nd row and 2nd data came into 1st row:
Replace
removeItem(position);
with
removeItem(holder.getAdapterPosition());
You initialize your recyclerView and adapter in onCreateView which was not appropriate.You have to override the method onViewCreated then initialize your recyclerView and adapter.try like this
public class NotificationFragment extends Fragment {
private RecyclerView NotificationRecyclerView;
private NotificationAdapter adapter;
private List<Friend> friendList;
public NotificationFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_notification, container, false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
NotificationRecyclerView.setHasFixedSize(true);
LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
NotificationRecyclerView.setLayoutManager(LayoutManager);
friendList = new ArrayList<>();
adapter = new NotificationAdapter(getContext(), friendList);
NotificationRecyclerView.setAdapter(adapter);
readAllNotification();
}
private void readAllNotification() {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Friend friend = snapshot.getValue(Friend.class);
if (firebaseUser.getUid().equals(friend.getReceiverID())) {
friendList.add(friend);
}
}
Collections.reverse(friendList);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Ok I just noticed you passed a parameter in removeItem method using holder.getAdapterPosition() which is causing your problem.Try to pass the position which is provided by public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position).So the basic error is when you are in onBindViewHolder you don't need to use holder.getAdapterPosition() because onBindViewHolder already giving you the position
In your removeItem method use notifyDataSetChanged instead of notifyItemRemoved(position)
try like this
#Override
public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position) {
final Friend friend = friendList.get(position);
holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase.getInstance().getReference("FriendRequest").child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
removeItem(position);
Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
}
});
}
});
}
public void removeItem(int position) {
friendList.remove(position);
notifyDataSetChanged();
}

DiffUtil with Async callback only displays list once and doesn't update

I am using DiffUtil async callback to update my list.
The problem is that it only displays the dataset once, at the first call. Later, when the dataset updates, the list only displays the items that were initially displayed. So the problem is that the dataset updates, but the list is stuck on its first state.(With the items that were initially created)
The dataset is being updated via a button click initiated by the user, this is how it looks:
private void updateUsersList() {
#Override
public void onResponse(JSONArray response) { // the JSON ARRAY response of user ids ["uid1", "uid334", "uid1123"]
for (int i = 0; i < response.length(); i++) {
try {
String userKey = response.get(i).toString(); // the currently iterated user id
final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userKeyRef = rootRef.child("users").child(userKey); // reference to currently iterated user
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
myDataset.add(new User(dataSnapshot.getKey(), dataSnapshot.child("imageUrl").getValue().toString())); //add new user: id and image url
mAdapter.updateList(myDataset);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
userKeyRef.addListenerForSingleValueEvent(listener);
}
catch (JSONException e) { Log.d(TAG, "message " + e); }
}
}
And this is my adapter using async DiffUtil:
public class MyAdapter extends RecyclerView.Adapter {
private AsyncListDiffer<User> mAsyncListDiffer;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView singleItemTextView;
public ImageView singleItemImage;
public View layout;
public ConstraintLayout constraintLayout;
public MyViewHolder(View v) {
super(v);
layout = v;
singleItemImage = (ImageView) v.findViewById(R.id.icon);
singleItemTextView = (TextView) v.findViewById(R.id.singleitemtv);
constraintLayout = (ConstraintLayout) v.findViewById(R.id.nbConstraintLayout);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter() {
DiffUtil.ItemCallback<User> diffUtilCallback = new DiffUtil.ItemCallback<User>() {
#Override
public boolean areItemsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.getUserId().equals(oldUser.getUserId());
}
#Override
public boolean areContentsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.equals(oldUser);
}
};
mAsyncListDiffer = new AsyncListDiffer<>(this, diffUtilCallback);
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.nb_image_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
User user = mAsyncListDiffer.getCurrentList().get(position);
Uri userImage = user.getImageUrl();
Log.d("test123", "user uri: " + userImage.toString());
holder.singleItemTextView.setText(user.getUserId());
Glide.with(holder.itemView.getContext() /* context */)
.load(userImage)
.into(holder.singleItemImage);
holder.constraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(v.getContext(), DisplayUserActivity.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mAsyncListDiffer.getCurrentList().size();
}
public void updateList(ArrayList<User> newList) {
mAsyncListDiffer.submitList(newList);
}
}
So why does my dataset update, but the list is stuck on first update only?

FirebaseRecyclerAdapter duplicating the objects in recycle view

My Structure:
I am developing a chat app by using firebase realtime database. I am using FirebaseRecyclerAdapter to display messages. But the thing is on scrolling, messages get duplicated and out of order.
Here is my implementation:
public class FirebaseChatActivity extends AppCompatActivity {
private String messageSenderId;
private String messageReceiverId;
private FirebaseRecyclerAdapter<ChatMessage, MessageViewHolder> firebaseRecyclerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_firebase_chat);
RecyclerView recyclerView = findViewById(R.id.rv_firebase_chat_activity);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
messageSenderId = "eoSU5m7PyucyC9h30JfHhV6S8Av2";
messageReceiverId = "ZOqofCid0XN5ovIAj1mXhRYxdnO2";
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("messages").child(messageSenderId).child(messageReceiverId);
FirebaseRecyclerOptions<ChatMessage> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<ChatMessage>()
.setQuery(query, ChatMessage.class)
.build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ChatMessage, MessageViewHolder>(firebaseRecyclerOptions) {
#Override
protected void onBindViewHolder(#NonNull MessageViewHolder messageViewHolder, int position, #NonNull ChatMessage message) {
if (message.getMessageType().equals("text")) {
messageViewHolder.showMessage.setText(message.getMessageText());
} else if (message.getMessageType().equals("image")) {
try {
Glide.with(getApplicationContext())
.load(message.getPhotoUrl())
.placeholder(R.drawable.no_image2)
.error(R.drawable.image_1)
.into(messageViewHolder.photoImageView);
} catch (Exception e) {
Log.d("MessageAdapterLog", e.toString());
}
}
}
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
android.view.View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_item_right, parent, false);
return new MessageViewHolder(view);
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
private class MessageViewHolder extends RecyclerView.ViewHolder {
public TextView showMessage;
public ImageView photoImageView;
public MessageViewHolder(#NonNull android.view.View itemView) {
super(itemView);
showMessage = itemView.findViewById(R.id.show_message);
photoImageView = itemView.findViewById(R.id.photo_image_view);
}
}
#Override
protected void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
if (firebaseRecyclerAdapter!= null) {
firebaseRecyclerAdapter.stopListening();
}
}
}
I have tried many different solutions e.g set as mentioned here as well as .addChildEventListener (completely different implementation) but unable to solve the issue.
Full Activity code as well as database structure is attached. Kindly let me know what I am doing wrong.
Thanks
The problem is that everytime you scroll, to make a new item visible again it will run the code inside your onBindViewHolder to inflate that view and rebind it.
if (message.getMessageType().equals("text")) {
messageViewHolder.showMessage.setText(message.getMessageText());
} else if (message.getMessageType().equals("image")) {
try {
Glide.with(getApplicationContext())
.load(message.getPhotoUrl())
.placeholder(R.drawable.no_image2)
.error(R.drawable.image_1)
.into(messageViewHolder.photoImageView);
} catch (Exception e) {
Log.d("MessageAdapterLog", e.toString());
}
}
}
to solve this problem you will need to override two methods inside your adapter
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}

why RecycleView items is not displayed?

I have a problem. When I use newsPojo at first - all displayed ok (but swipe to refresh is not work, when I use postAdapter.notifyDataSetChanged() - my items is not displayed. How can I fix it?
This is my Activity class
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private NewsApi newsApi;
private NewsPojo fromRetrofit;
private MainAdapter postAdapter;
#BindView(R.id.activity_main_swipe_to_refresh) SwipeRefreshLayout swipeRefreshLayout;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
fromRetrofit = new NewsPojo();
fromRetrofit.setArticles(new ArrayList<Article>());
response();
initRecycleView();
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
response();
swipeRefreshLayout.setRefreshing(false);
}
});
}
private void response() {
newsApi = RitApplication.getApi();
newsApi.getData().enqueue(new Callback<NewsPojo>() {
#Override
public void onResponse(Call<NewsPojo> call, Response<NewsPojo> response) {
fromRetrofit.getArticles().clear();
fromRetrofit = response.body();
postAdapter.notifyDataSetChanged();
}
}
#Override
public void onFailure(Call<NewsPojo> call, Throwable t) {
}
});
}
public void initRecycleView() {
recyclerView = findViewById(R.id.activity_main_recycle_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
postAdapter = new MainAdapter(fromRetrofit, new OnIteamClickListener() {
#Override
public void onItemClick(View itemView) {
}
}, getApplicationContext());
recyclerView.setAdapter(postAdapter);
}
}
Here you can see my Adapter class
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
private NewsPojo newsPojo;
private OnIteamClickListener listener;
private Context mContext;
public MainAdapter(NewsPojo newsPojo, OnIteamClickListener listener, Context mContext) {
this.newsPojo = newsPojo;
this.listener = listener;
this.mContext = mContext;
}
public void clear(){
newsPojo.getArticles().clear();
notifyDataSetChanged();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_news, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(newsPojo.getArticles().get(position));
}
#Override
public int getItemCount() {
if (newsPojo != null) {
return newsPojo.getArticles().size();
} else {
return 0;
}
}
Why postAdapter.notifyDataSetChanged(); is not working?
I suggest the following:
Change the following lines:
fromRetrofit.getArticles().clear();
fromRetrofit = response.body();
postAdapter.notifyDataSetChanged();
For this:
postAdapter.cleanAddArticles(response.body());
and in the adapter add the following:
public void cleanAddArticles(NewsPojo newsPj){
this.newsPojo.getArticles().clear();
this.newsPojo.getArticles().addAll(newsPj.getArticles());
notifyDataSetChanged();
}
Note: Error depending on the circumstances must be going through object references.
When you get new values by calling response() method, then you must call initRecycleView() to set the new values to the adapter, then use notifyDataSetChanged()
#Override
public void onResponse(Call<NewsPojo> call, Response<NewsPojo> response) {
fromRetrofit.getArticles().clear();
fromRetrofit = response.body();
initRecycleView() //*** Add this.
postAdapter.notifyDataSetChanged();
}
}
first of check when you swipe refresh that time your postAdapter not getting null other wise your code is ok.
if you want to make one separate method for adapter like below..
private void setAdater(){
if (postAdapter==null) {
postAdapter = new MainAdapter(fromRetrofit, new OnIteamClickListener() {
#Override
public void onItemClick(View itemView) {
}
}, getApplicationContext());
recyclerView.setAdapter(postAdapter);
}
else{
postAdapter.notifyDataSetChanged();
}
}
and also check your from fromRetrofit object what value have. i think adapter not getting any value bacause only clear article but object has some value there for i think you make object null when getting data...
fromRetrofit=null;
fromRetrofit = response.body();

Categories

Resources