为什么我得到"无法绘制回收的位图"?

时间:2013-05-24 02:45:13

标签: android bitmap

我正在使用位图,从原始位置创建一个新位置,然后将新位置设置为ImageView,当我回收原始内容时出现错误,但我没有绘制原始内容?有关详细信息,请在我的代码中阅读我的评论你可以看到我回收了我不能绘制的位图,我总是创建一个名为tile的新位图。

我的代码:

public void tileImage(Bitmap bm){
    if(bm==null){
        Debug.out("Bitmap is null");
    }
    else{
         Bitmap tile;
         float tileWidth = bm.getWidth();
         float tileHeight =1024;
 //if my bitmap is too wide
         if(bm.getWidth()>width){
             Debug.out("Bitmap too wide: "+bm.getWidth());
 //if this code runs I get no error, if not I get the error
             bm =  Bitmap.createScaledBitmap(bm,
                (int)width,
                (int)(bm.getHeight()*(float)(width/tileWidth)),
                false
                );
           }
         Debug.out("Bitmap height: "+bm.getHeight()+" adjusted width "+bm.getWidth());
 //if my bitmap is too tall
         if(bm.getHeight()>tileHeight){
              for(int i = 0; tileHeight*i<bm.getHeight(); i++){
                   image = new ImageView(main);
 //make tiles of the body
                    if((tileHeight*(i+1))<bm.getHeight()){
                         tile = Bitmap.createBitmap(
                                bm,
                                0, 
                                (int)(tileHeight*i),
                                (int)bm.getWidth(),
                                (int)(tileHeight)
                           );
                           Debug.out("Tiling: "+i);
                       }
 //tile the reaminder
                     else{
                           tile = Bitmap.createBitmap(
                               bm,
                               0, 
                               (int)(tileHeight*i),
                               (int)bm.getWidth(),
                               (int)(bm.getHeight()%tileHeight)
                          );
                           Debug.out("Tiling: "+bm.getHeight()%tileHeight+" "+i);
                     }  
                image.setImageBitmap(tile);
                tiles.addView(image);               
           }
         }
 //else its not too tall
    else{
        image = new ImageView(main);

        Debug.out("No tiling");

        tile = Bitmap.createBitmap(
                 bm,
                 0, 
                 0,
                 (int)bm.getWidth(),
                 (int)bm.getHeight()
                 );
        Debug.out("Bitmap too small height: "+bm.getHeight()+" width "+bm.getWidth());
            image.setImageBitmap(tile);
        tiles.addView(image); 

    }

  }
 //this is the trouble maker
bm.recycle();
}

2 个答案:

答案 0 :(得分:3)

  • Bitmap.createBitmap(params)从源位图的指定子集返回不可变位图。新位图可以是与源相同的对象,也可以是副本。

  • bitmap.recycle()方法释放与此位图关联的本机对象,并清除对像素数据的引用。这是一个高级调用,通常不需要调用,因为正常的GC进程将在没有更多对此位图的引用时释放此内存。

  • onDraw()方法需要一些时间才能使视图膨胀。如果您传递位图以绘制视图并在同一引用上调用recycle(),则位图将标记为“dead”,这意味着如果调用getPixels()或setPixels(),它将抛出异常,并且不会绘制任何内容

  • 您应该在onDestroy()中调用recycle()。

我的代码:

public class MainActivity extends Activity {
    private Bitmap mBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView image1 = (ImageView) findViewById(R.id.image1);
        mBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.ic_launcher);
        image1.setImageBitmap(mBitmap);
        tileImage();
    }

    private void tileImage() {
        ImageView image2 = (ImageView) findViewById(R.id.image2);
        Bitmap bm = Bitmap.createBitmap(mBitmap, 0, 0,
            (int) mBitmap.getWidth(), (int) mBitmap.getHeight());
        image2.setImageBitmap(bm);
    }

    @Override
    protected void onDestroy() {
        mBitmap.recycle();
        super.onDestroy();
    }
}

答案 1 :(得分:0)

上面的答案并不完全正确。实际上你应该等到onDestroy with recycle。特别是如果你大量使用创建这些位图。在收到OOM错误之前,您甚至可能无法访问onDestroy。您应该做的是测试您将其缩放到尺寸的尺寸到位图的尺寸。如果它们相等,则返回原始位图,不需要回收。否则,您将获得一个新的位图对象,您应该立即在原始位图上调用recyle。

请参阅http://developer.android.com/training/displaying-bitmaps/manage-memory.html