在RecycleView更新CardView项目时遇到延迟 [英] Encountering lag when updating a CardView item in a RecycleView

查看:222
本文介绍了在RecycleView更新CardView项目时遇到延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在与CardViews工作的问题。 I`ve创建了一个包含1的TextView和2 ImageViews一个CardView,这将会显示在RecycleView。当我尝试更新CardViews之一的内容(创建5卡进行测试)界面开始滚动了更新的存储卡时落后,但恢复到正常的当我通过的项目。它只有当ImageViews是present发生,代发言权ImageViews,与他们一些随机文本TextViews时,工作正常。

i'm having an issue working with CardViews . I`ve created a CardView containing 1 TextView and 2 ImageViews , which gets displayed in an RecycleView . When i try to update the contents of one of the CardViews (created 5 cards for testing) the interface starts to lag when scrolling over the updated card, but goes back to normal when i pass the item. It only happens when ImageViews are present , when substituting the ImageViews for say, TextViews with some random text in them, it works normally.

现在,这里是我的code,在那之后我会添加一些可能会造成更多的相关信息。

Now, here's my code , after that i'll add some more information that could be causing it.

首先,Adapter类,其中也包含物品类和List

First , the Adapter class, which also contains the items class and List :

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 , the 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);
               // ca.addItem(1,"test",bittest12,bittest22);
                break;
            default:
                break;
        }
    }
}

//------methods used for resizing the images down to smaller ones before loading into memory---//


public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
  }

最后,不是说我大概重要,我CardView XML。

And finally, not that i probably matters, 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>

现在,有人在另一个讨论表明我这是一个可能的原因:<一href=\"https://stackoverflow.com/questions/30667014/why-recyclerview-notifyitemchanged-will-create-a-new-viewholder-and-use-both-t\">Why RecyclerView.notifyItemChanged()将创建一个新ViewHolder并同时使用旧ViewHolder和新的?

Now , somebody in another discussion showed me this as a possible cause : Why RecyclerView.notifyItemChanged() will create a new ViewHolder and use both the old ViewHolder and new one?

所以我加了onBind和适配器的onCreate方法里面的日志项目,看是否可能会造成它,而事实上,它`不只是creatind一个额外ViewHolders,但其中3,每次我滚动在最近更新的卡,它似乎是重新结合,所述onBind方法似乎每次被调用。

So i added the Log items inside the onBind and onCreate methods of the Adapter to see if that could be causing it, and indeed, it`s not just creatind one additional ViewHolders, but 3 of them, and each time i scroll over the newly updated card, it seems to be re-binding, the onBind method seems to be called each time.

设置动画空为每个线程中的解决方案似乎并没有在我的情况下,任何的效果,所以也许that`s不会是什么原因造成的。

Setting the animation to 'null' as per the solution in the thread doesn't seem to have any effect in my case, so maybe that`s not what is causing it.

任何想法?

推荐答案

好吧,我解决了这个问题。看来只有当我通过XML的方法加载图像的情况发生,如果我有一个第三方库如毕加索加载它们,滞后似乎dissapear。是这样的:

Well, i solved it. It seems to happen only when i'm loading the images via the XML method, if i load them with a 3rd party library like Picasso, the lag seems to dissapear. Something like :

Picasso.with(context).load(MovieDetails.getPoster())
            .error(R.drawable.placeholder)
            .placeholder(R.drawable.placeholder)
            .into(movieViewHolder.imageViewPoster);

在onBindViewHolder内
和强似各地位图,只是通过对图像的URL或位置的字符串。和上下文传递到适配器类。

inside the onBindViewHolder and instead of passing around bitmaps, just pass a String for the URL or location of the image. And pass the Context to the Adapter class.

这篇关于在RecycleView更新CardView项目时遇到延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆