【发布时间】:2016-08-10 03:43:30
【问题描述】:
我正在使用 RecyclerView 和 Picasso 库来显示带有一些文本数据的很长的图像列表。我使用分页加载更多记录,一旦加载更多记录,毕加索就开始下载图像。我面临的主要问题是,当所有不可见的回收器视图项目以及可见项目都保存在内存中并且它正在消耗大量内存时。
我想为所有不可见的项目释放内存,一旦用户滚动,毕加索就会开始加载图像(从网络或缓存)。
以下是我在应用中实现的示例代码:
/**
* Adapter class used to display hotel list.
* Created by gaganpreetsingh on 1/18/2016.
*/
public class HotelListAdapter extends RecyclerView.Adapter<HotelDetailViewHolder> {
private Context mContext;
private List<HotelModel> mModelList;
private OnRecyclerItemClickListener mListener;
public HotelListAdapter(Context context, List<HotelModel> modelList,
OnRecyclerItemClickListener listener) {
this.mContext = context;
this.mModelList = modelList;
mListener = listener;
}
@Override
public HotelDetailViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_hotel_item, parent, false);
return new HotelDetailViewHolder(view, mListener);
}
@Override
public void onBindViewHolder(HotelDetailViewHolder holder, int position) {
holder.setItem(mContext, mModelList.get(position));
}
@Override
public int getItemCount() {
return mModelList.size();
}
}
下面是ViewHolder类的实现:
/**
* View holder class used to display a hotel with
* location and price.
* Created by gaganpreetsingh on 1/18/2016.
*/
public class HotelDetailViewHolder extends RecyclerView.ViewHolder
implements
View.OnClickListener {
private static final int MAX_WIDTH = 320;
private static final int MAX_HEIGHT = 186;
private ImageView mImgHotel;
private TextView mTxtHotelName;
private TextView mTxtAreaName;
private TextView mTxtHotelDistance;
private TextView mTxtPrice;
private View mRootView;
private OnRecyclerItemClickListener mListener;
private int mWidth, mHeight;
/**
* Initialize view holder
*
* @param itemView to initialize
*/
public HotelDetailViewHolder(View itemView, OnRecyclerItemClickListener listener) {
super(itemView);
mRootView = itemView;
mListener = listener;
mImgHotel = (ImageView) mRootView.findViewById(R.id.img_hotel);
mTxtHotelName = (TextView) mRootView.findViewById(R.id.txt_hotel_name);
mTxtAreaName = (TextView) mRootView.findViewById(R.id.txt_area_name);
mTxtHotelDistance = (TextView) mRootView.findViewById(R.id.txt_hotel_distance);
mTxtPrice = (TextView) mRootView.findViewById(R.id.txt_price);
mRootView.setOnClickListener(this);
}
/**
* Set the specified hotel details to this
* view holder
*
* @param model to set
*/
public void setItem(final Context context, final HotelModel model) {
ViewTreeObserver vto = mImgHotel.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
mImgHotel.getViewTreeObserver().removeOnPreDrawListener(this);
final int height = mImgHotel.getMeasuredHeight();
final int width = mImgHotel.getMeasuredWidth();
// get the target image view width and height
final int heightDp = AppUtils.getDpFromPx(height, context);
final int widthDp = AppUtils.getDpFromPx(width, context);
// if target image has higher size than our max image size,
// load image with max allowed size.
if (heightDp > MAX_HEIGHT || widthDp > MAX_WIDTH) {
// download resized image
PicassoUtils.loadImage(context, model.mImage, mImgHotel, MAX_WIDTH, MAX_HEIGHT);
} else {
// download resized image
PicassoUtils.loadImage(context, model.mImage, mImgHotel, widthDp, heightDp);
}
return true;
}
});
// PicassoUtils.loadImage(context, model.mImage, mImgHotel);
mTxtHotelName.setText(model.mName);
mTxtAreaName.setText(model.mArea);
}
@Override
public void onClick(View v) {
if (mListener != null)
mListener.onClick(mRootView, getAdapterPosition());
}
}
这是使用毕加索加载图像的代码:
public static void loadImage(Context context, String url, ImageView imageView,
int width, int height) {
Picasso.with(context).load(url)
.error(R.drawable.thumb_photo)
.placeholder(R.drawable.thumb_photo)
.resize(width, height)
.into(imageView);
}
此外,即使在加载调整大小的图像后,我有时也会遇到 OOM 异常。
请建议我一些方法来释放不可见项目的内存并避免 OOM 异常。
【问题讨论】:
-
我也遇到了类似的问题,你解决了吗?
-
在下面查看我的答案。
标签: android optimization memory-management android-recyclerview picasso