6

I understand how a ViewHolder's onBindViewHolder works, however I'm unclear about how notifyItemRangeChanged(0, this.data.size()); works in this example and what it does exactly.

The data that is supplied to this adapter is in Json format.

The adapter is below:

 public class AdapterQuestion extends RecyclerView.Adapter<AdapterQuestion.ViewQuestion>{

     private LayoutInflater mLayoutInflater;

     //this is an arrayList of questionData objects
     private ArrayList<QuestionData> data =new ArrayList<>();

     //Created the layoutInflator
     public AdapterQuestion(Context context){
          //get from context
          mLayoutInflater=LayoutInflater.from(context);
     }

     public void setBloglist(ArrayList<QuestionData> data){
         this.data =data;
         notifyItemRangeChanged(0, this.data.size());
     }

     @Override
     public ViewQuestion onCreateViewHolder(ViewGroup parent, int viewType) {
         //inflates the customQuestion view or converts it to java code
         View view= mLayoutInflater.inflate(R.layout.customquestion, null);

        //We now want to convert the View into a ViewQuestion, view Question takes
        //a view so we pass the view into view question and then return it.

        ViewQuestion holder=new ViewQuestion(view);
        return holder;
    }

    //ViewGroup parent and ViewType are not being assigned.
    @Override
    public void onBindViewHolder(ViewQuestion holder, int position) {
         //here we need to bind the data to our view, there is currently no Data!
         //We need to get the data from our JSON
         //Parameters is a ViewHolder and a Position
         //This gives us the current information object from the whole arraylist
         //data.get(position) data is the arraylist and we are getting the current position or index;
         //That current obj is of Type QuestionData

         QuestionData currentObj= data.get(position);

         //we are accessing the Inflated view, or saved view with holder
         //holder.answerText is the textView in holder. We are then taking that current object
         //We are getting the text of the current object and setting it to the AnswerText view
         holder.answerText.setText(currentObj.getMtext());
         holder.answerId.setText(currentObj.getId());
         holder.mVotes.setText(currentObj.getVotes());
         holder.mLikeButton.setTag(currentObj);
     }

    @Override
    public int getItemCount() {
         return data.size();
    }

    public class ViewQuestion extends RecyclerView.ViewHolder{
        //once we create it once the reclycer view will automatically recycle it
        private TextView answerText;
        private TextView answerId;
        private TextView mVotes;
        private LikeButton mLikeButton;

        public ViewQuestion (View itemView){
            super(itemView);
            //here we are finding the views by their ID
            answerText=(TextView)itemView.findViewById(R.id.answerText);
            answerId=(TextView)itemView.findViewById(R.id.answerId);
            mVotes=(TextView)itemView.findViewById(R.id.VoteTextView);
            mLikeButton=    (LikeButton)itemView.findViewById(R.id.heart_buttons);

            mLikeButton.setOnLikeListener(new OnLikeListener() {

                @Override
                public void liked(LikeButton likeButton) {
                    Voting vote = new Voting();
                    vote.onUpVote(convertToString(), 
                            getAdapterPosition(),ViewQuestion.this);
                    System.out.print("Adapter Position"+getAdapterPosition());
                }

                @Override
                public void unLiked(LikeButton likeButton) {
                     Voting onDown=new Voting();
                     onDown.onDownVote(convertToString(), 
                             getAdapterPosition(), ViewQuestion.this);

                }
            });
        }

        public String getVoteView(){
            String voteView=mVotes.getText().toString();
            return voteView;
        }

        public String convertToString(){
            String converted=answerId.getText().toString();
            return converted;
        }

        public int convertToInt(){
            String converted=answerId.getText().toString();
            int ConvertedInt=Integer.parseInt(converted);
            return ConvertedInt;
        }
    }
}
Ori Lentz
  • 3,668
  • 6
  • 22
  • 28
eli
  • 335
  • 1
  • 3
  • 18
  • `notifyItemRangeChanged` is your custom method in your adapter, you need to call it for your Mainclass where you setAdapter. – Kathi Apr 04 '16 at 03:39
  • have you checked the docs? : `http://developer.android.com/intl/zh-cn/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemRangeChanged(int, int)` – Yazan Apr 04 '16 at 08:19
  • Formatted code and description, hopefully for better readability (kept all code as it is, but OP might want to consider reducing it to just the needed parts, rather than the entire code dump). – Ori Lentz Apr 06 '16 at 05:33
  • please accept the answer if this was helpful so that it will be easier for others too – erluxman Aug 02 '17 at 04:39

3 Answers3

9

When the data that is to be set in RecyclerView is changed, the Adapter needs to get notified of the data change so that it can change the data in recyclerview.

The method

notifyItemRangedChanged(fromIndex,toIndex);

is used to notify the adapter that some set of data is changed among the whole data and it tells the adapter that adapter should refresh the data and reload it into the recyclerView starting from fromIndex to toIndex as passed into the method .

use this method if you have multiple data changed but not all , those changed data also are in cluster so that you can say from 5th to 10th index data are changed .

If all data are changed call :

notifyDataSetChanged();

if only one dataItem is changed then call :

notifyItemChanged(dataPosition);
erluxman
  • 18,155
  • 20
  • 92
  • 126
  • 1
    Something seems not right here. The second parameter of notifyItemRangedChanged is itemCount. It is not toIndex. The function notifyItemRangeChanged(int positionStart, int itemCount) notify any registered observers that the itemCount items starting at position positionStart have changed. – user2818066 Nov 30 '20 at 08:16
  • See here for working example : https://stackoverflow.com/a/38796098/3904109 – DragonFire Feb 19 '21 at 05:53
  • Is `notifyDataSetChanged` the exact same as `notifyItemRangeChanged(0, this.data.size())` ? – android developer Feb 15 '23 at 09:48
1

Using notifyItemRangeChanged(0, this.data.size()) it’s bad practice. Best way is using notifyItemChanged or notifyItemRangeChanged with payload.

Payload - optional parameter (key). That give you opportunity to check what kind of update do you need.

public void onBindViewHolder(/*...*/, List payloads) {
    if (payloads.isEmpty()) {
        setText(holder, position);
        downloadBitmap(holder, position);
    } else if (payloads.contains(SET_ONLY_TEXT)){
        setText(holder, position);
    }
}

In this example payloads used for checking when adapter should update only the text.

ilyagorbunov
  • 593
  • 3
  • 9
0

in your case you are not doing it(notifyItemRangeChanged) right as you might as well can call notifyDataSetChanged(); because you are telling the adapter that the entire list has changed and not specific position.

Aniruddha K.M
  • 7,361
  • 3
  • 43
  • 52