-1

RecyclerViewとPicassoライブラリを使用して、テキストデータを含む非常に長い画像リストを表示しています。より多くのレコードをロードするためにページネーションを使用しました。さらに多くのレコードがロードされるとすぐに、Picassoはイメージのダウンロードを開始しました。私が直面している主な問題は、見えないアイテムと一緒に見えないリサイクルのビューアイテムがすべてメモリに保持され、多くのメモリを消費していることです。RecyclerビューでPicassoを使用してメモリを増やす

すべての非表示項目のメモリを解放したいと思います。ユーザーがスクロールするとすぐに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例外を回避する方法をお勧めします。

+0

あなたはまだこれを理解なかった私は、同様の問題が生じていますか? – Lion789

+0

下記の私の答えを参照してください。 –

答えて

0

この問題は、サイズ変更されたイメージをターゲットImageViewのサイズに等しいサイズでダウンロードして解決しました。 ImageViewの実際の寸法を計算するために、私はViewTreeObserverを使用しました。

以下

はViewHolderピカソを使用して画像をダウンロードするサンプルコードです:

ViewTreeObserver vto = mImgHotel.getViewTreeObserver(); 
      if(vto == null || !vto.isAlive()) return; 
      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); 

        // download resized image 
        PicassoUtils.loadImage(context, model.mImage, mImgHotel, widthDp, heightDp); 

        return true; 
       } 
      }); 
+0

ピカソで画像を読み込むたびにたくさんの余計な作業がありますが、これは効率的ですか? – Lion789

+0

このコードを実装することで、OOMの例外がほとんど解決されました。今私はピカソを使用してOOMの例外がゼロです。 –

+0

私はPicasso.with.load.intoなどを呼び出すアダプタでこれをどのように実装するのですか?また、画像が100枚あれば、これはそれぞれ1つずつ適用する意味ですか? – Lion789

関連する問題