I have a problem with CardView. I created a CardView containing 1 TextView and 2 ImageViews that are displayed in a RecycleView. When I try to update the contents of one of the maps (5 maps created for testing), the interface starts to lag while scrolling through the updated map, but returns when I pass the element. This only happens when ImageViews are present when replacing ImageViews, say TextViews with some random text in them, it works fine.
Now, here is my code, after that I will add additional information that can cause it.
First, the Adapter class, which also contains the items and List class:
public class MovieDetailsAdapter extends RecyclerView.Adapter<MovieDetailsAdapter.MovieViewHolder> { public List<MovieDetails> movieList; private static final String TAG = "MyAdapter"; public MovieDetailsAdapter() { movieList = new ArrayList< MovieDetails>(); } public void setItemCount(int count ,String title, Bitmap poster,Bitmap fanart ) { movieList.clear(); movieList.addAll(generateDummyData(count, title, poster , fanart)); notifyDataSetChanged(); } @Override public int getItemCount() { return movieList.size(); } public void addItem(int position,String title, Bitmap poster, Bitmap fanart) { if (position > movieList.size()) return; movieList.add(position, generateDummyItem(title, poster, fanart)); // notifyDataSetChanged(); notifyItemInserted(position); } public void updateItem(int position, String title, Bitmap poster, Bitmap fanart) { if (position > movieList.size()) return; movieList.add(position, generateDummyItem(title, poster, fanart)); notifyItemChanged(position); // notifyDataSetChanged(); } @Override public MovieViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View itemView = LayoutInflater. from(viewGroup.getContext()). inflate(R.layout.card_layout_movies, viewGroup, false); Log.d(TAG, "create header view holder"); return new MovieViewHolder(itemView); } @Override public void onBindViewHolder(MovieViewHolder movieViewHolder, int i) { Log.d(TAG, "bind header view holder"); MovieDetails mdet = movieList.get(i); movieViewHolder.vTitle.setText(mdet.Title); movieViewHolder.vPoster.setImageBitmap(mdet.imageViewPoster); movieViewHolder.vFanart.setImageBitmap(mdet.imageViewFanart); Log.d(TAG, "position: " + i + " holder: " + movieViewHolder + " text: " + movieViewHolder.vTitle); } public static class MovieViewHolder extends RecyclerView.ViewHolder { protected TextView vTitle; protected ImageView vPoster; protected ImageView vFanart; public MovieViewHolder(View v) { super(v); vTitle = (TextView) v.findViewById(R.id.title); vPoster = (ImageView) v.findViewById(R.id.imageViewPoster); vFanart = (ImageView) v.findViewById(R.id.imageViewFanart); } } public static class MovieDetails { protected String title; protected Bitmap imageViewPoster; protected Bitmap imageViewFanart; public MovieDetails(String title, Bitmap imageViewPoster,Bitmap imageViewFanart ) { this.title = title; this.imageViewPoster = imageViewPoster; this.imageViewFanart = imageViewFanart; } } public static MovieDetails generateDummyItem(String title, Bitmap poster, Bitmap fanart) { MovieDetails mov = new MovieDetails(title, poster, fanart); return mov; } public static List< MovieDetailsAdapter.MovieDetails> generateDummyData(int count, String title , Bitmap imageViewPoster, Bitmap imageviewFanart) { ArrayList<MovieDetailsAdapter.MovieDetails> items = new ArrayList<MovieDetailsAdapter.MovieDetails>(); for (int i=0; i < count; i++) { items.add(new MovieDetailsAdapter.MovieDetails(title, imageViewPoster, imageviewFanart)); } return items; }
}
Now, here is my main class, activity class
public class MoviesListActivity extends AppCompatActivity { public MovieDetailsAdapter ca = new MovieDetailsAdapter(); public RecyclerView recList; private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_movies_list); RecyclerView recList = (RecyclerView) findViewById(R.id.cardList); LinearLayoutManager llm = new LinearLayoutManager(this); llm.setOrientation(LinearLayoutManager.VERTICAL); recList.setLayoutManager(llm); button = (Button) findViewById(R.id.button); MyOnClickListener Listener = new MyOnClickListener(); button.setOnClickListener(Listener); recList.setItemAnimator(null); Bitmap bittest1 = decodeSampledBitmapFromResource(getResources(), R.drawable.poster_example, 640, 955); Bitmap bittest2 = decodeSampledBitmapFromResource(getResources(), R.drawable.fanart_example, 800, 450); ca.setItemCount(5, "TestingTitle", bittest1, bittest2); recList.setAdapter(ca); } public class MyOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: Bitmap bittest12 = decodeSampledBitmapFromResource(getResources(), R.drawable.poster2, 640, 955); Bitmap bittest22 = decodeSampledBitmapFromResource(getResources(), R.drawable.fanart2, 800, 450); Toast.makeText(getApplicationContext(), "msg msg", Toast.LENGTH_SHORT).show(); ca.updateItem(1, "test", bittest12, bittest22);
And finally, not what I probably matter, my CardView XML.
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="match_parent" card_view:cardCornerRadius="4dp" android:layout_margin="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="20dp" android:background="@color/bkg_card" android:text="Movie Title" android:gravity="center_vertical" android:textColor="@android:color/white" android:textSize="14dp"/> <ImageView android:elevation="5dp" android:scaleType="fitCenter" android:layout_width="100dp" android:layout_height="150dp" android:id="@+id/imageViewPoster" android:text="Poster" android:gravity="center_vertical" android:layout_below="@id/title" android:layout_marginTop="10dp" android:layout_marginLeft="5dp"/> <ImageView android:id="@+id/imageViewFanart" android:scaleType="fitCenter" android:layout_alignBottom="@+id/imageViewPoster" android:layout_toEndOf="@+id/imageViewPoster" android:layout_width= "235dp" android:layout_height="122dp" android:layout_marginRight="5dp"/> </RelativeLayout>
Now someone in another discussion showed me this as a possible reason: Why will RecyclerView.notifyItemChanged () create a new ViewHolder and use both the old ViewHolder and the new?
So, I added log elements inside the adapterβs onBind and onCreate methods to find out if this could be the reason for this, and indeed, itβs not just creative, but also one of them, but 3 of them, and every time I scroll through to a new updated map, it seems that it is being bound again, the onBind method seems to be called every time.
Setting the animation to "null" according to the solution in the stream does not seem to have any effect in my case, so maybe this is not what causes it.
Any ideas?