Need an Example About Recyclerview.Adapter.Notifyitemchanged(Int Position, Object Payload)

Need an example about RecyclerView.Adapter.notifyItemChanged(int position, Object payload)

Check out this sample code that demonstrates the feature. It's a RecyclerView that calls notifyItemChanged(position, payload) when the item at position position is clicked. You can verify that onBindViewHolder(holder, position, payload) was called by looking for the logcat statement.

Make sure you are using at least version 23.1.1 of the support libraries, like so:

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:cardview-v7:23.1.1'
}

HelloActivity.java

package com.formagrid.hellotest;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.CardView;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

public class HelloActivity extends Activity {

private RecyclerView mRecyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
mRecyclerView.setAdapter(new HelloAdapter());
DefaultItemAnimator animator = new DefaultItemAnimator() {
@Override
public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) {
return true;
}
};
mRecyclerView.setItemAnimator(animator);
}

private static class HelloAdapter extends RecyclerView.Adapter<HelloAdapter.HelloViewHolder> {

public class HelloViewHolder extends RecyclerView.ViewHolder {

public TextView textView;

public HelloViewHolder(CardView cardView) {
super(cardView);
textView = (TextView) cardView.findViewById(R.id.text_view);
}

}

@Override
public HelloViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate(
R.layout.card_item, parent, false);
return new HelloViewHolder(cardView);
}

@Override
public void onBindViewHolder(HelloViewHolder holder, int position) {
bind(holder);
}

@Override
public void onBindViewHolder(HelloViewHolder holder, int position, List<Object> payload) {
Log.d("butt", "payload " + payload.toString());
bind(holder);
}

@Override
public int getItemCount() {
return 20;
}

private void bind(final HelloViewHolder holder) {
holder.textView.setText("item " + holder.getAdapterPosition());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final int position = holder.getAdapterPosition();
Log.d("butt", "click " + position);
HelloAdapter.this.notifyItemChanged(position, "payload " + position);
}
});
}

}

}

activity_main.xml

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".HelloActivity">

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</RelativeLayout>

card_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="100dip"
android:layout_margin="5dip"
card_view:cardElevation="5dip">

<TextView
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</android.support.v7.widget.CardView>

Android Recyclerview notifyItemChanged(position ,payLoad) don't work if the view at that position is not visible on screen or scrolled out

From the RecyclerView.Adapter#notifyItemChanged(int position, java.lang.Object payload) docs:

Adapter should not assume that the payload will always be passed to onBindViewHolder(), e.g. when the view is not attached, the payload will be simply dropped.

So when the cell at currently selected position is scrolled out of the screen, nothing will change because the old selected view is not exist.

You can modify your arrayList to store the selected status in it, or add a method to CalendarCallbacks which can fetch the current selected position, but you must take care of changing the selected position when needed.

Using notifyItemChange(position,payloads)

It is better to used the future onactivityresult in android

It is easy to used make the changes below in your recycle on item clicked method

Make movie model class implement serializable.

Apply below changes to your MainActivity:

Movie movie = movieList.get(mposition);
Intent intent=new Intent(MainActivity.this,ChangeMovie.class);
intent.putExtra("passposition",mposition);
intent.putExtra("movie",movie);
startActivityForResult(i, 100);

Override the below method

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if (requestCode == 100 && resultCode == Activity.RESULT_OK) {

int listpos = mIntent.getIntExtra("listpos", --1);
if(listpos!=-1){

Movie movie = (Movie) data.getSerializable("movie");

movieList.set(listpos,movie);

if(mAdapter!=null){
mAdapter.notifyDataSetChanged
}
}
}
}

apply below changes in your ChangeMovie

get the list position in your on create method

int pos = -1;
int mposition = getIntent().getExtra().getInt("mposition");

in your save button clicked

newmovie=newmoviefield.getText().toString();
Intent intent = new Intent();
intent.putExtra("movie", changemovie);
intent.putExtra("passposition",mposition);
setResult(RESULT_OK, intent);
finish();

Let me know if still have issues, as code is written manually might be you have to correct some case sensitive thanks

How do I pass a payload to RecyclerView.Adapter.notifyItemChanged?

I have checked with an existing project and it works. See:

notifyItemChanged with payload

Its not about the sdk, i guess you are using an older version of the Library Containing the recyclerview and its adapter. Thats the Version I am using in my example.

    compile 'com.android.support:recyclerview-v7:23.0.0'

Requesting an Example for RecyclerViewAdapter.notifyItemChanged for Imageview

  1. First of all your Cards data class should have an alpha property initialize with value 255 for a fully visible image.

  2. In onBindViewHolder use

    viewHolder.ivCardImage.setImageAlpha(mData.get(position).getAlpha());

  3. Then in your click event

    @Override
    public void onClick(View view) {
    ....
    mData.get(position).setAlpha(70);
    notifyItemChanged(position);
    }
    }

RecyclerView.Adapter.notifyItemChanged() never passes payload to onBindViewHolder()

RecyclerView by default creates another copy of the ViewHolder in order to fade the views into each other. This causes the problem because the old ViewHolder gets the payload but then the new one doesn't. So you need to explicitly tell it to reuse the old one:

DefaultItemAnimator animator = new DefaultItemAnimator() {
@Override
public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) {
return true;
}
};
mRecyclerView.setItemAnimator(animator);

Recyclerview adapter onBindViewHolder payload is not working

Firstly, it seems you are just adding the item and want to change something in it with payloads right away.

Obviously, when you just add a new one, the whole item has to be drawn, thus no payloads needed.

Only then, when it is already drawn and you want to change some elements, you may use payloads with notifyItemChanged (if one item was changed) or notifyItemRangeChanged (if several items were changed).

Secondly, I am not sure regarding the range you use.

The first argument of notifyItemRangeChanged is the start index.

The second one is how many items you want to change.

Thirdly, it's not clear where do you call the addRecordDefault
So make sure you called notifyItemChanged or notifyItemRangeChanged with payloads.

why payloads in RecyclerView' onBindViewHolder is a list?

From Android Docs:

Partial bind vs full bind:

The payloads parameter is a merge list from notifyItemChanged(int,
Object) or notifyItemRangeChanged(int, int, Object). If the payloads
list is not empty, the ViewHolder is currently bound to old data and
Adapter may run an efficient partial update using the payload info. If
the payload is empty, Adapter must run a full bind. Adapter should not
assume that the payload passed in notify methods will be received by
onBindViewHolder(). For example when the view is not attached to the
screen, the payload in notifyItemChange() will be simply dropped.

It's a list because it's a merge list. You could have potentially called notifyItemChanged multiple times before the view is updated, each time with a potentially different payload.

For example, at the same time, multiple threads could simultaneously request an item update with payloads "fav count update" and "icon change" and "time stamp update". So it's not wise to assume your payload is the 0th item.



Related Topics



Leave a reply



Submit