RecyclerView滚动时滞后

滚动浏览RecyclerView时,我无法理解刹车的原因是什么。 滚动由mRecyclerView.smoothScrollToPosition(position);调用mRecyclerView.smoothScrollToPosition(position); 滚动抽搐列表时(渲染时间范围> 16ms)

AlphaAdapter.java

 public class AlphaAdapter extends RecyclerView.Adapter { private static final String TAG = "AlphaAdapter"; private Context mContext; private List mGunList; private boolean isAnimate; private final int VIEW_TYPE_NULL = 0; private final int VIEW_TYPE_ITEM = 1; public AlphaAdapter(Context mContext, List mGunList) { this.mContext = mContext; this.mGunList = mGunList; } public AlphaAdapter(Context mContext, List mGunList, boolean a) { this.mContext = mContext; this.mGunList = mGunList; this.isAnimate = a; } @Override public int getItemViewType(int position) { try { if (mGunList.get(position).getNameWeapon().equals("")) return VIEW_TYPE_NULL; else return VIEW_TYPE_ITEM; } catch (Exception e) { e.printStackTrace(); Log.e("AlphaAdapter", String.valueOf(position)); return VIEW_TYPE_NULL; } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = null; if (viewType == VIEW_TYPE_ITEM) view = LayoutInflater.from(mContext).inflate(R.layout.item_game, parent, false); else view = LayoutInflater.from(mContext).inflate(R.layout.item_null, parent, false); return new ViewHolder(view); } @Override public void onViewDetachedFromWindow(ViewHolder holder) { super.onViewDetachedFromWindow(holder); holder.itemView.clearAnimation(); } @Override public boolean onFailedToRecycleView(ViewHolder holder) { return true; } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onBindViewHolder(final ViewHolder holder, int position) { try { long startTime = System.currentTimeMillis(); if (!getWeapon(position).getNameWeapon().equals("")) { if (isAnimate) { if (mLastAnimPosition < position) { mLastAnimPosition = position; Animation a = AnimationUtils.loadAnimation(mContext, R.anim.item_game_anim); holder.itemView.startAnimation(a); a.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } }); } } Picasso.with(mContext) .load("file:///android_asset/" + getWeapon(position).getImagePath()) .placeholder(R.drawable.loading) .error(R.drawable.load_fail) .into(holder.image); holder.main.setText(getWeapon(position).getNameWeapon()); holder.desc.setText(getWeapon(position).getNameSkin()); } Log.i(TAG, String.valueOf(System.currentTimeMillis() - startTime) + "ms onBind (" + String.valueOf(position) + ");"); } catch (Exception e) { e.printStackTrace(); } } @Override public long getItemId(int position) { return position; } private PrimaryWeapon getWeapon(int position) { return mGunList.get(position); } @Override public int getItemCount() { return mGunList.size(); } class ViewHolder extends RecyclerView.ViewHolder { TextView main, desc; ImageView image; ViewHolder(View itemView) { super(itemView); main = (TextView) itemView.findViewById(R.id.item_textMain); desc = (TextView) itemView.findViewById(R.id.item_textDescription); image = (ImageView) itemView.findViewById(R.id.item_image); } } } 

参与适配器的布局元素包括LinearLayout,ImageView,2 TextView。

起初我认为下载图像的问题,尝试将它们加载到AsyncTask中,通过毕加索上传位图而没有,但毕竟从他们的标记中删除,列表仍然会滞后。

要在滚动后转储RAM,它会在添加后显示最初有71个内存实例ViewHolder

 @Override public boolean onFailedToRecycleView(ViewHolder holder) { return true; } 

这个值减少到15-16, 虽然RecyclerView的速率 – 5副本,它应该覆盖它们,但滚动时不会创建新的。 截图1

item_null.xml

    

item_game.xml

       

回答这里接受的答案:

Context如何成为适配器上的内存泄漏? 或者甚至让它变慢? 无论如何它只附加到Activity的RecyclerView ……一旦Activity消失,上下文就与适配器一起进行GC编辑。 不仅如此,从视图中获取Context总是会返回同一个,所以它没用,并且无需任何调用函数。 您甚至可以将适配器设置为静态内部类,以便您可以直接访问它,而不是使用声明的字段。 简而言之,上下文不是您发生内存泄漏的原因。

那么可能是什么问题呢? 我想你需要在每次绑定到ViewHolder时取消Picasso上的图像请求,如下所示:

  Picasso.with(context).cancelRequest(holder.image); 

您可能还希望为所有人执行此操作,以防活动被销毁(但不是因为方向更改),但这取决于您的需求。

我建议也尝试使用Glide库。 它似乎更现代,仍然保持着。

您正在将上下文传递给适配器。 首先,这可能会导致内存泄漏,也可能影响您的性能。 而不是将上下文传递给适配器,只需从ViewHolder中获取它。 您始终可以在RecyclerView.Adapter中获取上下文引用,而无需传递它。

要在滚动后转储RAM,它会显示最初有71个内存实例ViewHolder。

从转储来看,这很可能就是这种情况。

 @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Context context = parent.getContext(); ... } @Override public void onBindViewHolder(final ViewHolder holder, int position) { Context context = holder.itemView.getContext(); ... }