2013-03-21 83 views
1

當我通過我的GridView來回滾動時,我的圖像沒有正確回收,並最終在整個網格中顯示相同的圖像。Gridview回收問題與asynctask

Recycling problem

適配器

public class ImageAdapter extends BaseAdapter { 
    private Context mContext; 
    private List<String> mList; 
    private int mheight; 
    private int mwidth; 
    private Bitmap nBitmap; 

    public ImageAdapter(Context context, List<String> list, int height, int width) { 
     mContext = context; 
     mList = list; 
     mheight = height; 
     mwidth = width; 
    } 

    @Override 
    public int getCount() { 
     return mList.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     return mList.get(position).toString(); 
    } 

    @Override 
    public long getItemId(int position) { 
     return 0; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ImageView imageView; 
     if (convertView == null) { 
      imageView = new ImageView(mContext); 
      InputStream is; 
      try { 
       is = mContext.getAssets().open(mList.get(position)); 
       Bitmap bm = BitmapFactory.decodeStream(is); 
       Bitmap mBitmap = Bitmap.createScaledBitmap(bm, mwidth/3, mwidth/3, false); 
       imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 

       this.nBitmap = mBitmap; 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } else { 
      imageView = (ImageView) convertView; 
     } 
     imageView.setImageBitmap(nBitmap); 
     return imageView; 
    } 
} 

我想工作快位關閉UI線程滾動解碼,但縮略圖過得去1啓動應用程序時加載1和再生縮略圖視圖也會從改變orignal視圖和低低memoery設備應用程序崩潰,同時從這裏加載AsyncTask的縮略圖更新codde

public class ImageAdapter extends BaseAdapter { 
private Context mContext; 
private List<String> mList; 
private int mheight; 
private int mwidth; 
private InputStream is; 

public ImageAdapter(Context context, List<String> list, int height, int width) { 
    mContext = context; 
    mList = list; 
    mheight = height; 
    mwidth = width; 
} 


@Override 
public int getCount() { 
    return mList.size(); 
} 

@Override 
public Object getItem(int position) { 
    return mList.get(position).toString(); 
} 

@Override 
public long getItemId(int position) { 
    return 0; 
} 





@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ImageView imageView; 
    if (convertView == null) { 
     imageView = new ImageView(mContext); 
    } else { 
     imageView = (ImageView) convertView; 
    } 


    InputStream is; 
    try { 
     is = mContext.getAssets().open(mList.get(position)); 
     Loadimage task = new Loadimage(imageView , mheight , mwidth); 
     task.execute(is); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return imageView ; 

} 
public class Loadimage extends AsyncTask<InputStream, Void, Bitmap>{ 
private final WeakReference<ImageView> imageViewReference; 


private InputStream is = null; 
private int width; 


public Loadimage(ImageView imageView, int mheight, int mwidth) { 
    imageViewReference = new WeakReference<ImageView>(imageView); 
    this.width=mwidth; 

    // TODO Auto-generated constructor stub 
} 

@Override 
protected Bitmap doInBackground(InputStream... params) { 
    is = params[0]; 

    if (is !=null) { 

     Bitmap bitmap = BitmapFactory.decodeStream(is); 
     Bitmap nBitmap =Bitmap.createScaledBitmap(bitmap,width/3 , width/3, false); 
     return nBitmap;  
    } 
    return null; 
    } 
@Override 
protected void onPostExecute(Bitmap bitmap) { 
    if (imageViewReference != null && bitmap != null) { 
     final ImageView imageView = imageViewReference.get(); 
     if (imageView != null) { 
      imageView.setImageBitmap(bitmap); 
      imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 
     } 


} 

}

+0

如果convertView = NULL,什麼是nBitmap?可能是上次在那裏裝載的。您需要更改位圖加載的位置。 – eyespyus 2013-03-21 23:49:13

+0

好吧,當我嘗試重新加載位圖滾動變得非常滯後 – Joseph27 2013-03-22 00:29:36

回答

3

您需要將生成位圖的塊移到if/then之外。現在,您只在convertView == null時生成新的位圖。

我相信你的代碼是正確的,因爲:

public class ImageAdapter extends BaseAdapter { 
    private Context mContext; 
    private List<String> mList; 
    private int mheight; 
    private int mwidth; 

    public ImageAdapter(Context context, List<String> list, int height, int width) { 
     mContext = context; 
     mList = list; 
     mheight = height; 
     mwidth = width; 
    } 

    @Override 
    public int getCount() { 
     return mList.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     return mList.get(position).toString(); 
    } 

    @Override 
    public long getItemId(int position) { 
     return 0; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ImageView imageView; 
     if (convertView == null) { 
      imageView = new ImageView(mContext); 
     } else { 
      imageView = (ImageView) convertView; 
     } 

     InputStream is; 
     try { 
      is = mContext.getAssets().open(mList.get(position)); 
      Bitmap bm = BitmapFactory.decodeStream(is); 
      Bitmap bitmap = Bitmap.createScaledBitmap(bm, mwidth/3, mwidth/3, false); 
      imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 

      imageView.setImageBitmap(bitmap); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return imageView; 
    } 
} 

您滾動不會很流暢,你會得到很多的丟幀現象,因爲你的位圖解碼代碼是低效的(沒有緩存) ,而且這一切都發生在UI線程上,這對響應性不利。當前代碼中的瓶頸不是ImageView的分配和垃圾回收。

瓶頸是(可能遠遠)您的處理和創建Bitmap s。

您可以諮詢以下鏈接看看:

Displaying Bitmaps Efficiently

而具體這一個!

Processing Bitmaps Off the UI Thread

+0

我嘗試了他們兩個,它的工作原理是沒有回收和滾動非常滯後 – Joseph27 2013-03-22 00:07:10

+0

我相當確定問題不是因爲它不再回收。我認爲你的位圖生成速度很慢。如果你有一個位圖緩存,並且你加載它們而不是解碼流,那麼它會快很多。 – yarian 2013-03-22 00:37:41

+0

我更新了我的答案。 – yarian 2013-03-22 00:43:08