zoukankan      html  css  js  c++  java
  • Bitmap处理之创建可自动回收资源的ImageView

    1.创建可自动回收资源的BitmapDrawable

    继承BitmapDrawable,设置标志位 mCacheRefCount cache计数,mDisplayRefCount 显示计数,mHasBeenDisplayed判断是否已经显示过了具体的code:

        private int mCacheRefCount = 0;  //cache计数
        private int mDisplayRefCount = 0; //显示计数
    
        private boolean mHasBeenDisplayed;//是否已经显示过

    判断bitmap是否还存在并且可用

        private synchronized boolean hasValidBitmap() {
            Bitmap bitmap = getBitmap();
            return bitmap != null && !bitmap.isRecycled();
        }

    判断bitmap的状态

        private synchronized void checkState() {
            // If the drawable cache and display ref counts = 0, and this drawable
            // has been displayed, then recycle
            if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
                    && hasValidBitmap()) {
    
                getBitmap().recycle();
            }
        }


    通过cache计数,显示计数,是否已经显示,以及bitmap是否还存在,如果四个条件都满足,就显式的回收bitmap资源


    判断bitmap是否已经cache

        public void setIsCached(boolean isCached) {
            synchronized (this) {
                if (isCached) {
                    mCacheRefCount++;
                } else {
                    mCacheRefCount--;
                }
            }
    
            // Check to see if recycle() can be called
            checkState();
        }

    调用的地方是,如果已经将某个bitmap加入了cache(memory cache,disk cache)setIsCached(true)这时cache计数就会增加1,如果某个bitmap从cache中删除,就setIsCached(false)这时cache计数就减去1,然后调用checkState()方法,来判断bitmap是否需要回收

    判断bitmap是否已经显示


        public void setIsDisplayed(boolean isDisplayed) {
            synchronized (this) {
                if (isDisplayed) {
                    mDisplayRefCount++;
                    mHasBeenDisplayed = true;
                } else {
                    mDisplayRefCount--;
                }
            }
    
            // Check to see if recycle() can be called
            checkState();
        }

    完整的代码

    public class RecyclingBitmapDrawable extends BitmapDrawable {
    
        static final String LOG_TAG = "CountingBitmapDrawable";
    
        private int mCacheRefCount = 0;
        private int mDisplayRefCount = 0;
    
        private boolean mHasBeenDisplayed;
    
        public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) {
            super(res, bitmap);
        }
    
        /**
         * Notify the drawable that the displayed state has changed. Internally a
         * count is kept so that the drawable knows when it is no longer being
         * displayed.
         *
         * @param isDisplayed - Whether the drawable is being displayed or not
         */
        public void setIsDisplayed(boolean isDisplayed) {
            synchronized (this) {
                if (isDisplayed) {
                    mDisplayRefCount++;
                    mHasBeenDisplayed = true;
                } else {
                    mDisplayRefCount--;
                }
            }
    
            // Check to see if recycle() can be called
            checkState();
        }
    
        /**
         * Notify the drawable that the cache state has changed. Internally a count
         * is kept so that the drawable knows when it is no longer being cached.
         *
         * @param isCached - Whether the drawable is being cached or not
         */
        public void setIsCached(boolean isCached) {
            synchronized (this) {
                if (isCached) {
                    mCacheRefCount++;
                } else {
                    mCacheRefCount--;
                }
            }
    
            // Check to see if recycle() can be called
            checkState();
        }
    
        private synchronized void checkState() {
            // If the drawable cache and display ref counts = 0, and this drawable
            // has been displayed, then recycle
            if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
                    && hasValidBitmap()) {
                if (BuildConfig.DEBUG) {
                    Log.d(LOG_TAG, "No longer being used or cached so recycling. "
                            + toString());
                }
    
                getBitmap().recycle();
            }
        }
    
        private synchronized boolean hasValidBitmap() {
            Bitmap bitmap = getBitmap();
            return bitmap != null && !bitmap.isRecycled();
        }
    
    }


    2.创建可自动回收资源的ImageView

    基于RecyclingBitmapDrawable来实现 RecyclingImageView

    具体实现

    重载Imageiew的setImageDrawable()方法

        public void setImageDrawable(Drawable drawable) {
            // Keep hold of previous Drawable
            final Drawable previousDrawable = getDrawable();
    
            // Call super to set new Drawable
            super.setImageDrawable(drawable);
    
            // Notify new Drawable that it is being displayed
            notifyDrawable(drawable, true);
    
            // Notify old Drawable so it is no longer being displayed
            notifyDrawable(previousDrawable, false);
        }
    在设置时,显获得前一个drawable资源,然后发出通知,通知的是实现

        private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
            if (drawable instanceof RecyclingBitmapDrawable) {
                // The drawable is a CountingBitmapDrawable, so notify it
                ((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
            } else if (drawable instanceof LayerDrawable) {
                // The drawable is a LayerDrawable, so recurse on each layer
                LayerDrawable layerDrawable = (LayerDrawable) drawable;
                for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
                    notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
                }
            }
        }
    主要是调用RecyclingBitmapDrawable的setIsDisplayed方法,在通过ImageView设置时,当前的Drawable的显示计数加1,而前一个Drawable资源的显示计数减1,然后检查状态,这样前一个Drawable资源就有可能被回收

  • 相关阅读:
    开放个人电脑端口[Windows]
    mysql局域网服务搭建
    JS数据分组[JSON]
    网站缓存【我只是单纯的保存网站!】
    JS生成数字加减乘法验证码
    【http反向代理】多个域名指向同一个ip的不同网站解决方法
    JQuery获取ID含有特殊字符的DOM元素
    java.lang.NoClassDefFoundError: org/apache/commons/collections4/ListValuedMap
    大型网站技术架构,6网站的伸缩性架构之分布式缓存集群的伸缩性设计
    大型网站技术架构,6网站的伸缩性架构之应用服务器集群的伸缩性设计
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3037439.html
Copyright © 2011-2022 走看看