//出错的函数是这样的Bitmap btSrc = Bitmap.createBitmap(....);
Matrix mx = new Matrix();
int clipX = .. , clipY = .. ,clipW = ..,clipH = ..;for(int i=0;i<5;i++){ Bitmap btMid = Bitmap.createBitmap(btSrc, 0, 0, btSrc.getWidth(), btSrc.getHeight(), mx, true);
Bitmap btClip = Bitmap.createBitmap(btMid, clipX,clipY,clipW,clipH);
        
        if(btMid!=null&&!btMid.isRecycled()){
btMid.recycle(); //释放图片占用的堆栈内存。
btMid = null;
}
        if(btClip!=null&&!btClip.isRecycled()){
btClip.recycle();
btClip = null;
}}在i = 2 时,发生Canvas: trying to use a recycled bitmap错误。
btMid 和 btClip 是局部变量,每次用完后就recycle()了,下个循环里又是新的,怎么会使用同一个变量内存呢??

解决方案 »

  1.   

    ....杯具吧,recycle只是给系统发个消息,通知系统回头可以回收这个位图占用的内存了,不代表你调用完recycle系统就马上给free掉,recycle只是一个通知而已。
      

  2.   

    看源码public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
                Matrix m, boolean filter) {        checkXYSign(x, y);
            checkWidthHeight(width, height);
            if (x + width > source.getWidth()) {
                throw new IllegalArgumentException("x + width must be <= bitmap.width()");
            }
            if (y + height > source.getHeight()) {
                throw new IllegalArgumentException("y + height must be <= bitmap.height()");
            }        // check if we can just return our argument unchanged
            if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
                    height == source.getHeight() && (m == null || m.isIdentity())) {
                return source;
            }        int neww = width;
            int newh = height;
            Canvas canvas = new Canvas();
            Bitmap bitmap;
            Paint paint;        Rect srcR = new Rect(x, y, x + width, y + height);
            RectF dstR = new RectF(0, 0, width, height);        if (m == null || m.isIdentity()) {
                bitmap = createBitmap(neww, newh,
                        source.hasAlpha() ? Config.ARGB_8888 : Config.RGB_565);
                paint = null;   // not needed
            } else {
                /*  the dst should have alpha if the src does, or if our matrix
                    doesn't preserve rectness
                */
                boolean hasAlpha = source.hasAlpha() || !m.rectStaysRect();
                RectF deviceR = new RectF();
                m.mapRect(deviceR, dstR);
                neww = Math.round(deviceR.width());
                newh = Math.round(deviceR.height());
                bitmap = createBitmap(neww, newh, hasAlpha ? Config.ARGB_8888 : Config.RGB_565);
                if (hasAlpha) {
                    bitmap.eraseColor(0);
                }
                canvas.translate(-deviceR.left, -deviceR.top);
                canvas.concat(m);
                paint = new Paint();
                paint.setFilterBitmap(filter);
                if (!m.rectStaysRect()) {
                    paint.setAntiAlias(true);
                }
            }
            
            // The new bitmap was created from a known bitmap source so assume that
            // they use the same density
            bitmap.mDensity = source.mDensity;
            
            canvas.setBitmap(bitmap);
            canvas.drawBitmap(source, srcR, dstR, paint);        return bitmap;
        }    /**
         * Returns a mutable bitmap with the specified width and height.  Its
         * initial density is as per {@link #getDensity}.
         *
         * @param width    The width of the bitmap
         * @param height   The height of the bitmap
         * @param config   The bitmap config to create.
         * @throws IllegalArgumentException if the width or height are <= 0
         */
        public static Bitmap createBitmap(int width, int height, Config config) {
            Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
            bm.eraseColor(0);    // start with black/transparent pixels
            return bm;
        }
      

  3.   


            // check if we can just return our argument unchanged
            if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
                    height == source.getHeight() && (m == null || m.isIdentity())) {
                return source;
            }

     Bitmap btMid = Bitmap.createBitmap(btSrc, 0, 0, btSrc.getWidth(), btSrc.getHeight(), mx, true);    
    btMid 会返回btSrc对象 你把btMid recycle了实际就是把btSrc给回收了 下次用当然报错了
    你可以Debug下这两个的ID
      

  4.   


    这个m.identify()的涵义是不是上一个matrix和这一个matrix是同一对象?
      

  5.   

    这个是数学问题 矩阵有恒等矩阵,你前面new的Matrix就是恒等矩阵,满足上面这个条件会把传进的对象直接返回。而你又把这个对象给recycle了
      

  6.   


    哦,明白了。
    那意思就是btMid和btClip和btSrc相同都是某一对象的引用,
    Bitmap.createBitmap只是创建了两个引用而已,对吗?
      

  7.   


    我刚试了,btMid、btClip和btSrc的hashCode是相同的。
      

  8.   

    是的 只要改下createBitmap的几个参数来保证不会返回原来的对象。
      

  9.   

    是不是Bitmap.createBitmap 不用回收了???
      

  10.   


    你看看createBitmap的原函数,参数中某个或某几个不变(排列组合),再看创建出的bitmap的hashcode是否一样就知道了。
      

  11.   

    楼主最后怎么解决的啊?
    我也遇到了这个问题,如果在缩放之前释放还是会报java.lang.OutOfMemoryError: bitmap size exceeds VM budget异常。