2

I'm making a CommentFragment. I have a RecyclerView to list comments and a Edittext to write comment. However when I add a comment it's sent to server but RecyclerView isn't updated. I use notifydatasetchanged to update. Code:

 private void getComments(){

    Call<List<CommentsModel>> call=restApiClass.getComments(post_id);
    call.enqueue(new Callback<List<CommentsModel>>() {
        @Override
        public void onResponse(Call<List<CommentsModel>> call, Response<List<CommentsModel>> response) {

            if(response.isSuccessful()){

                list=response.body();
                if(commentsAdapter==null) {
                    commentsAdapter = new CommentsAdapter(list, getContext());
                }
                else{
                    commentsAdapter.notifyDataSetChanged();
                }
                recyclerView.setAdapter(commentsAdapter);
            }

        }
        @Override
        public void onFailure(Call<List<CommentsModel>> call, Throwable t) {
        }
    });
}

I call this method when I click to sendCommentTextView:

  sendCommentTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

              //............send comment codes.........
               getComments();

        }
    });
Mehmet Gür
  • 503
  • 7
  • 20
  • 1
    You call `notifyDataSetChanged()`, but you never change the data set! You need to set the response list on your adapter first. – Nicolas Apr 18 '20 at 21:30

2 Answers2

2

check this correct answer: notifyDataSetChanged example.

I think you should follow there the answer to make the adapter work as expected with notifyDataSetChanged(). Shortly: you have to update the list inside the adapter and then notify to it that the list has been updated, so it will render again on ui (recyclerview).

PS: after notifyDataSetChanged function, you don't have to set the adapter again on the recyclerview if already assigned.

GabrieleG
  • 107
  • 1
  • 7
1

Here you updated the list when Retrofit brings new data back, but actually you didn't feed your adapter with this data; you just called commentsAdapter.notifyDataSetChanged();, but you need first to add a method like updateList(List<CommentsModel> list) in your adapter, and call it with updateList(list); before using commentsAdapter.notifyDataSetChanged();

So, add updateList(List<CommentsModel> list) into your adapter to update its list internally like Below:

class CommentsAdapter extends RecyclerView.Adapter<CommentsAdapter.ViewHolder> {
    ...

    List<CommentsModel> mList;

    updateList(List<CommentsModel> list) {
        this.mList.clear();
        this.mList.addAll(list);
    }

}

And then the change in your code could be something like:

call.enqueue(new Callback<List<CommentsModel>>() {
    @Override
    public void onResponse(Call<List<CommentsModel>> call, Response<List<CommentsModel>> response) {

        if(response.isSuccessful()){

            list=response.body();
            if(commentsAdapter==null) {
                commentsAdapter = new CommentsAdapter(list, getContext());
            }
            else{
                commentsAdapter.updateList(list);
                commentsAdapter.notifyDataSetChanged();
            }
            recyclerView.setAdapter(commentsAdapter);
        }

    }
    @Override
    public void onFailure(Call<List<CommentsModel>> call, Throwable t) {
    }
});

Update

Yes it's working but recylerview return to first position and list reload. But I want to load only last comment. Other comments must stay same. So how can I do that ?

To just update the last comment in your list, then add a new method into your adapter that takes only that comment, and add it to the list like:

class CommentsAdapter extends RecyclerView.Adapter<CommentsAdapter.ViewHolder> {
    ...

    List<CommentsModel> mList;

    addComment(CommentsModel comment) {
        this.mList.add(comment);
        notifyItemInserted(mList.size()-1);
    }

}

Then when the data comes in back by Retrofit:

call.enqueue(new Callback<List<CommentsModel>>() {
    @Override
    public void onResponse(Call<List<CommentsModel>> call, Response<List<CommentsModel>> response) {

        if(response.isSuccessful()){

            list = response.body();
            if(commentsAdapter == null) {
                commentsAdapter = new CommentsAdapter(list, getContext());
            }
            else{
                // updating the adapter list with the last comment 
                commentsAdapter.addComment((CommentsModel) list.get(list.size()-1));

            }
            recyclerView.setAdapter(commentsAdapter);
        }

    }
    @Override
    public void onFailure(Call<List<CommentsModel>> call, Throwable t) {
    }
});
Zain
  • 37,492
  • 7
  • 60
  • 84
  • @Zahin Thanks for answer. I use `this.list.clear();` and `this.list.addAll(list);` in method. Yes it's working but recylerview return to first position and list reload. But I want to load only last comment. Other comments must stay same. So how can I do that ? – Mehmet Gür Apr 18 '20 at 22:02
  • Now also I'm using `commentsAdapter.notifyItemInserted(list.size());` instead of `commentsAdapter.notifyDataSetChanged();` but there is still same problem. – Mehmet Gür Apr 18 '20 at 22:04
  • I want to ask you my last question. The comment is added and list not reload. But last comment hide in soft keyboard. Do you know is there any method like recyclerview.setCurrentPosition(position) @Zain – Mehmet Gür Apr 18 '20 at 22:32
  • 1
    @MehmetGür please try this `((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);` – Zain Apr 18 '20 at 22:35
  • I have tested this with 2 phone and I sent comments same time. But sometimes only one of the comments were showed. And to show other comment I have to reopen Fragment. I couldn't find why? Do you have an advice for this? @Zain – Mehmet Gür Apr 20 '20 at 18:41
  • 1
    @MehmetGür I think it's because you loaded the current comments on your mobile (say Mob.A) before sending the new comment first from mobile (say Mob.B) ; and you need to have a LiveData mechanism in retrieving retrofit data so that all mobiles can receive updated commentss (like in whatsapp). please see [this article](https://medium.com/@pivincii/using-retrofit-with-livedata-5c5a49544ba3) – Zain Apr 20 '20 at 18:49
  • 1
    Thanks again @Zain I'll see that article. – Mehmet Gür Apr 20 '20 at 19:01