欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

【Android Developers Training】 59. 管理圖片

系統 2894 0

注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術一般,由于喜愛安卓而產生了翻譯的念頭,純屬個人興趣愛好。

原文鏈接: http://developer.android.com/training/displaying-bitmaps/manage-memory.html


接著上一節課的步伐,還有很多特定的事情可以讓垃圾回收和位圖重用變得容易。根據你的目標Android系統的不同版本,推薦的策略也會有所不同。這系列課程的樣例代碼: BitmapFun (鏈接: http://www.cnblogs.com/jdneo/p/3512517.html )向你展示了你的應用如何在不同的Android版本間有效率地工作。

在開始這堂課之前,我們先來看一下Android對于位圖存儲管理的演變:

  • 在Android 2.2(API Level 8)之前,當垃圾回收發生時,你應用的線程會停止。由此導致的延遲會降低應用的性能表現。 在Android 2.3開始加入了并發式的垃圾回收,這意味著當一個位圖不再被引用時,對應的內存會被迅速回收
  • 在Android 2.3.3(API Level 10)之前,一副位圖的依托像素數據(backing pixel data)存儲于本機內存中。它和位圖本身是分離開的,位圖存儲于 Dalvik堆中。本機內存中的像素數據并不會以一種可預測的形式進行釋放,因此可能會導致一個應用超過它的內存限制而崩潰。 從Android 3.0(API Level 11)開始,像素數據和與其關聯的位圖都存儲于Dalvik堆中了

下面的章節將會描述如何對不同的Android版本,優化位圖存儲管理。


一). 在Android 2.3.3及之前的系統版本上管理內存

在Android 2.3.3(API Level 10)及以前,推薦使用 recycle() 。如果你在你的應用中要顯示大量的位圖數據,你極有可能引起 OutOfMemoryError 錯誤。 recycle() 可以讓應用盡快地釋放內存。

Caution:

只有當你確定對應的位圖將不再被使用的情況下,你才應該使用 recycle() 。如果你使用了 recycle() ,并在之后嘗試繪制該位圖,那么你將會得到這樣的錯誤提示:“ Canvas: trying to use a recycled bitmap.

下面的代碼是調用 recycle() 的樣例。它使用引用計數(變量“ mDisplayRefCount ”以及“ mCacheRefCount ”)來追蹤位圖是否是當前正在顯示或是在緩存中。當下列情況發生時,代碼會回收位圖:

  • mDisplayRefCount ”以及“ mCacheRefCount ”的引用計數都為0。
  • 位圖不是“ null ”,同時它還未被回收。
      
        private
      
      
        int
      
       mCacheRefCount = 0
      
        ;


      
      
        private
      
      
        int
      
       mDisplayRefCount = 0
      
        ;

...


      
      
        //
      
      
         Notify the drawable that the displayed state has changed.


      
      
        //
      
      
         Keep a count to determine when the drawable is no longer displayed.
      
      
        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.


      
      
        //
      
      
         Keep a count to determine when the drawable is no longer being cached.
      
      
        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()) {

        getBitmap().recycle();

    }

}




      
      
        private
      
      
        synchronized
      
      
        boolean
      
      
         hasValidBitmap() {

    Bitmap bitmap 
      
      =
      
         getBitmap();

    
      
      
        return
      
       bitmap != 
      
        null
      
       && !
      
        bitmap.isRecycled();

}
      
    

二).?在Android 3.0及以后的系統版本上管理內存

Android 3.0(API Level 11)引入了 BitmapFactory.Options.inBitmap 域。如果配置了該選項,接受該 Options 對象的解碼方法會在加載內容時嘗試去重用已經存在的位圖。這意味著位圖內存被重用了,從而提高了性能表現,同時免去了內存分配和回收的工作。然而,對于如何使用 inBitmap 會有一些限制。特別地,在Android 4.4(API Level 19)之前,只有尺寸吻合的位圖才被支持。更多詳細信息,可以閱讀: inBitmap

保存一幅位圖以備將來使用

下面的代碼樣例展示了在相同的應用中,一個已經存在的位圖是如何為了將來可能被再次使用到而保存的。當一個應用在Android 3.0及以上的設備上運行,且一個位圖從 LruCache 中移除,該位圖的軟引用會放置在一個 HashSet 中,以備之后 inBitmap 使用:

      Set<SoftReference<Bitmap>>
      
         mReusableBitmaps;


      
      
        private
      
       LruCache<String, BitmapDrawable>
      
         mMemoryCache;




      
      
        //
      
      
         If you're running on Honeycomb or newer, create a


      
      
        //
      
      
         synchronized HashSet of references to reusable bitmaps.
      
      
        if
      
      
         (Utils.hasHoneycomb()) {

    mReusableBitmaps 
      
      =
      
        

            Collections.synchronizedSet(
      
      
        new
      
       HashSet<SoftReference<Bitmap>>
      
        ());

}



mMemoryCache 
      
      = 
      
        new
      
       LruCache<String, BitmapDrawable>
      
        (mCacheParams.memCacheSize) {



    
      
      
        //
      
      
         Notify the removed entry that is no longer being cached.
      
      
            @Override

    
      
      
        protected
      
      
        void
      
       entryRemoved(
      
        boolean
      
      
         evicted, String key,

            BitmapDrawable oldValue, BitmapDrawable newValue) {

        
      
      
        if
      
       (RecyclingBitmapDrawable.
      
        class
      
      
        .isInstance(oldValue)) {

            
      
      
        //
      
      
         The removed entry is a recycling drawable, so notify it

            
      
      
        //
      
      
         that it has been removed from the memory cache.
      
      

            ((RecyclingBitmapDrawable) oldValue).setIsCached(
      
        false
      
      
        );

        } 
      
      
        else
      
      
         {

            
      
      
        //
      
      
         The removed entry is a standard BitmapDrawable.
      
      
        if
      
      
         (Utils.hasHoneycomb()) {

                
      
      
        //
      
      
         We're running on Honeycomb or later, so add the bitmap

                
      
      
        //
      
      
         to a SoftReference set for possible use with inBitmap later.
      
      
                        mReusableBitmaps.add

                        (
      
      
        new
      
       SoftReference<Bitmap>
      
        (oldValue.getBitmap()));

            }

        }

    }

....

}
      
    

使用一個存在的位圖

在運行的程序中,解碼方法檢查是否有可用的位圖。例如:

      
        public
      
      
        static
      
      
         Bitmap decodeSampledBitmapFromFile(String filename,

        
      
      
        int
      
       reqWidth, 
      
        int
      
      
         reqHeight, ImageCache cache) {



    
      
      
        final
      
       BitmapFactory.Options options = 
      
        new
      
      
         BitmapFactory.Options();

    ...

    BitmapFactory.decodeFile(filename, options);

    ...



    
      
      
        //
      
      
         If we're running on Honeycomb or newer, try to use inBitmap.
      
      
        if
      
      
         (Utils.hasHoneycomb()) {

        addInBitmapOptions(options, cache);

    }

    ...

    
      
      
        return
      
      
         BitmapFactory.decodeFile(filename, options);

}
      
    

下面的代碼是上述代碼中 addInBitmapOptions() 方法的實現。它尋找一個存在的位圖,并將它作為 inBitmap 的值。注意,該方法僅僅在它找到了一個合適的匹配時,才將位圖設置為 inBitmap 的值(你的代碼不可以假定這個匹配一定能找到):

      
        private
      
      
        static
      
      
        void
      
      
         addInBitmapOptions(BitmapFactory.Options options,

        ImageCache cache) {

    
      
      
        //
      
      
         inBitmap only works with mutable bitmaps, so force the decoder to

    
      
      
        //
      
      
         return mutable bitmaps.
      
      

    options.inMutable = 
      
        true
      
      
        ;



    
      
      
        if
      
       (cache != 
      
        null
      
      
        ) {

        
      
      
        //
      
      
         Try to find a bitmap to use for inBitmap.
      
      

        Bitmap inBitmap =
      
         cache.getBitmapFromReusableSet(options);



        
      
      
        if
      
       (inBitmap != 
      
        null
      
      
        ) {

            
      
      
        //
      
      
         If a suitable bitmap has been found, set it as the value of

            
      
      
        //
      
      
         inBitmap.
      
      

            options.inBitmap =
      
         inBitmap;

        }

    }

}




      
      
        //
      
      
         This method iterates through the reusable bitmaps, looking for one 


      
      
        //
      
      
         to use for inBitmap:
      
      
        protected
      
      
         Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {

        Bitmap bitmap 
      
      = 
      
        null
      
      
        ;



    
      
      
        if
      
       (mReusableBitmaps != 
      
        null
      
       && !
      
        mReusableBitmaps.isEmpty()) {

        
      
      
        synchronized
      
      
         (mReusableBitmaps) {

            
      
      
        final
      
       Iterator<SoftReference<Bitmap>>
      
         iterator

                    
      
      =
      
         mReusableBitmaps.iterator();

            Bitmap item;



            
      
      
        while
      
      
         (iterator.hasNext()) {

                item 
      
      =
      
         iterator.next().get();



                
      
      
        if
      
       (
      
        null
      
       != item &&
      
         item.isMutable()) {

                    
      
      
        //
      
      
         Check to see it the item can be used for inBitmap.
      
      
        if
      
      
         (canUseForInBitmap(item, options)) {

                        bitmap 
      
      =
      
         item;



                        
      
      
        //
      
      
         Remove from reusable set so it can't be used again.
      
      
                                iterator.remove();

                        
      
      
        break
      
      
        ;

                    }

                } 
      
      
        else
      
      
         {

                    
      
      
        //
      
      
         Remove from the set if the reference has been cleared.
      
      
                            iterator.remove();

                }

            }

        }

    }

    
      
      
        return
      
      
         bitmap;

}
      
    

最后,此方法決定備選的位圖是否符合 inBitmap 的尺寸標準:

      
        static
      
      
        boolean
      
      
         canUseForInBitmap(

        Bitmap candidate, BitmapFactory.Options targetOptions) {



    
      
      
        if
      
       (Build.VERSION.SDK_INT >=
      
         Build.VERSION_CODES.KITKAT) {

        
      
      
        //
      
      
         From Android 4.4 (KitKat) onward we can re-use if the byte size of

        
      
      
        //
      
      
         the new bitmap is smaller than the reusable bitmap candidate

        
      
      
        //
      
      
         allocation byte count.
      
      
        int
      
       width = targetOptions.outWidth /
      
         targetOptions.inSampleSize;

        
      
      
        int
      
       height = targetOptions.outHeight /
      
         targetOptions.inSampleSize;

        
      
      
        int
      
       byteCount = width * height *
      
         getBytesPerPixel(candidate.getConfig());

        
      
      
        return
      
       byteCount <=
      
         candidate.getAllocationByteCount();

    }



    
      
      
        //
      
      
         On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
      
      
        return
      
       candidate.getWidth() ==
      
         targetOptions.outWidth

            
      
      && candidate.getHeight() ==
      
         targetOptions.outHeight

            
      
      && targetOptions.inSampleSize == 1
      
        ;

}




      
      
        /**
      
      
        

 * A helper function to return the byte usage per pixel of a bitmap based on its configuration.

 
      
      
        */
      
      
        static
      
      
        int
      
      
         getBytesPerPixel(Config config) {

    
      
      
        if
      
       (config ==
      
         Config.ARGB_8888) {

        
      
      
        return
      
       4
      
        ;

    } 
      
      
        else
      
      
        if
      
       (config ==
      
         Config.RGB_565) {

        
      
      
        return
      
       2
      
        ;

    } 
      
      
        else
      
      
        if
      
       (config ==
      
         Config.ARGB_4444) {

        
      
      
        return
      
       2
      
        ;

    } 
      
      
        else
      
      
        if
      
       (config ==
      
         Config.ALPHA_8) {

        
      
      
        return
      
       1
      
        ;

    }

    
      
      
        return
      
       1
      
        ;

}
      
    

【Android Developers Training】 59. 管理圖片存儲


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美xxxxx69xxxx | 国产精品久久久久久久久久 | 亚洲高清中文字幕综合网 | 超碰免费观看 | 深夜做爰性大片中文 | 亚洲日本中文字幕永久 | 成人高清视频免费观看 | 精品日本三级在线观看视频 | 免费观看毛片 | 欧美搞b | 国产成人精品一区二区仙踪林 | a级成人毛片久久 | 91在线播放网站 | 91精品国产综合久久久久久 | 九色国产在线 | 中文字幕一区在线观看视频 | 国产精品久久久久久日本 | 精品一二区 | 青青热在线观看视频精品 | 日本高免费观看在线播放 | 国产日韩一区二区 | a视频在线观看免费 | 欧美人在线 | 国产精品尤物在线 | 成年人在线观看视频 | 91p在线观看 | 日本一区二区三区免费观看 | 成人瑟瑟 | 四色成人av永久网址 | 波多野结衣中文字幕2022免费 | 国产精品九九久久99视频 | 日韩免费一区二区三区 | 三级在线国产 | 久久精品视频在线观看 | 国产亚洲福利精品一区 | 国产精品区免费视频 | 日韩视频在线免费观看 | 91国内精品久久久久免费影院 | 精品国产一区在线观看 | 高清videosgratis欧美live | 全色网站|