【问题标题】:ListView of bitmaps runs out of memory位图的 ListView 内存不足
【发布时间】:2014-02-08 00:03:58
【问题描述】:

我让用户在 ImageView 上绘制东西,然后单击保存以保存绘图。稍后,用户可以在一个 ListView 中看到所有保存的绘图,该 ListView 具有一个 ImageView 和两个带有一些细节的 TextView。

为避免保存和检索位图,我将绘制的所有 xy 点存储在 txt 文件中,并在使用 createBitmap 方法绘制点并在适配器内的 ImageView 上设置位图时重新创建位图。

当用户删除或更新列表时,我完成并重新启动列表活动以重新加载文件并重新创建所有这些位图,但以前的位图没有被回收,因为我不知道在哪里调用回收方法!!

所以问题自然是有时我会因为所有位图而出现 OutOfMemory 错误。 问题:我在哪里可以为位图调用回收,或者我如何在不使用这么多内存的情况下实现它 这是列表适配器

public class CustomGalleryListAdapter extends ArrayAdapter<String>{
private final Activity context;
private final String[] name_plus_details;
private final String[] imageinfo;
public CustomGalleryListAdapter(Activity context,
String[] name_plus_details, String[] imageinfo) {
super(context, R.layout.gallery_list_single_item_layout, name_plus_details);
this.context = context;
this.name_plus_details = name_plus_details;
this.imageinfo = imageinfo;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
    Paint mPaint,mPaint2;
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLUE);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(23/4);

    mPaint2 = new Paint();
    mPaint2.setAntiAlias(true);
    mPaint2.setDither(true);
    mPaint2.setColor(Color.GREEN);
    mPaint2.setStyle(Paint.Style.STROKE);
    mPaint2.setStrokeJoin(Paint.Join.ROUND);
    mPaint2.setStrokeCap(Paint.Cap.ROUND);
    mPaint2.setStrokeWidth(17/4);


    LayoutInflater inflater = context.getLayoutInflater();
    Bitmap mBitmap = Bitmap.createBitmap(600/5, 700/5, Bitmap.Config.ARGB_8888);
    Canvas mCanvas = new Canvas(mBitmap);
    String[] imagedata = imageinfo[position].split(":");
    String[] points;
    for(int i=0;i<imagedata.length;i++){
        if(imagedata[i].contains(";")){
            points=imagedata[i].split(";");
            if(points[0].length()>0){
                int drawx1 = Integer.parseInt(points[0].split(",")[0]);
                int drawy1 = Integer.parseInt(points[0].split(",")[1]);
                mCanvas.drawCircle(drawx1/5, drawy1/5, 15/4, mPaint2);
            }
            for(int h=0;h+1<points.length-1;h++){
                int drawx1 = Integer.parseInt(points[h].split(",")[0]);
                int drawy1 = Integer.parseInt(points[h].split(",")[1]);
                int drawx2 = Integer.parseInt(points[h+1].split(",")[0]);
                int drawy2 = Integer.parseInt(points[h+1].split(",")[1]);
                mCanvas.drawLine(drawx1/5, drawy1/5, drawx2/5, drawy2/5, mPaint);
            }
        }
    }
    View rowView= inflater.inflate(R.layout.gallery_list_single_item_layout, null, true);
    TextView detailsTextView = (TextView) rowView.findViewById(R.id.txt);
    TextView name_field = (TextView) rowView.findViewById(R.id.gallery_name_field);

    ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
    imageView.setImageDrawable(new BitmapDrawable(getContext().getResources(),mBitmap));
    imageView.setScaleType(ImageView.ScaleType.FIT_XY);      
    imageView.setBackgroundColor(Color.GRAY);
    String[] text_parts = name_plus_details[position].split("ENDNAME");
    name_field.setText(text_parts[0]);
    detailsTextView.setText("\n"+text_parts[1]);

    return rowView;

}
}

【问题讨论】:

  • 尝试重用你的行布局。根本不要给它充气 getView 调用。在 getView 执行时出现内存不足错误是很正常的。
  • 我很抱歉,但我不太明白......你能解释一下吗?当您说“重用行布局”时,您的意思是释放当前不在屏幕上的列表项?

标签: android bitmap out-of-memory


【解决方案1】:

首先 - 阅读以下内容: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

我认为,据我了解,您已经为您的位图制作了类似图集的东西 - 这看起来好多了。

使用此解决方案还将为您提供一种非常方便的方式来处理位图: http://developer.android.com/reference/android/util/LruCache.html#entryRemoved(boolean, K, V, V)

【讨论】:

    【解决方案2】:

    尝试使用支架,这样您就不会为每个单元格膨胀视图,因为您只是在重复使用它们。看看这个:http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder 网上也有很多例子告诉你如何在 ArrayAdapter 中使用 holder

    【讨论】:

    • 我是 android 的初学者,所以我想我有功课要做。我会检查一下,但请告诉我......你的方法会以什么方式节省内存?我仍然需要为整个列表创建位图,所以有什么变化?
    • 我想如果您使用支架,您的记忆力会显着提高。测试一下,让我知道
    • 我不反对..我只是想更好地理解这个概念。 (以防您没有注意到我没有将位图存储为位图。我以编程方式重新创建它们)
    • 是的,但是现在您还要重新创建整个视图,这非常消耗内存
    • 所以你的方法解决了我的代码的一些其他问题。不是回收位图问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 2013-05-08
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    相关资源
    最近更新 更多