免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
07.Android之多媒體問題

目錄介紹

  • 7.0.0.1 加載bitmap圖片的時候需要注意什么?為何bitmap容易造成OOM?如何計算Bitmap占用內存?
  • 7.0.0.2 如何理解recycle釋放內存問題?圖片加載到內存其實有兩部分數(shù)據(jù),這是為何?
  • 7.0.0.3 如何在不壓縮圖片的情況下加載高清大圖?加載圖的機制是什么,為何不會內存泄漏?
  • 7.0.0.7 LRU算法的原理?核心思想是什么?如果緩存滿了的話,什么方法來管理移除最近最少使用的item和添加新的item?

好消息

  • 博客筆記大匯總【15年10月到至今】,包括Java基礎及深入知識點,Android技術博客,Python學習筆記等等,還包括平時開發(fā)中遇到的bug匯總,當然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續(xù)完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計500篇[近100萬字],將會陸續(xù)發(fā)表到網上,轉載請注明出處,謝謝!
  • 鏈接地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起于忽微,量變引起質變!所有的筆記將會更新到GitHub上,同時保持更新,歡迎同行提出或者push不同的看法或者筆記!

7.0.0.1 加載bitmap圖片的時候需要注意什么?為何bitmap容易造成OOM?如何計算Bitmap占用內存?

  • 注意問題
    • 直接加載大容量的高清Bitmap很容易出現(xiàn)顯示不完整、內存溢出OOM的問題,所以最好按一定的采樣率將圖片縮小后再加載進來
    • 為減少流量消耗,可對圖片采用內存緩存策略,又為了避免圖片占用過多內存導致內存溢出,最好以軟引用方式持有圖片
    • 如果還需要網上下載圖片,注意要開子線程去做下載的耗時操作技術博客大總結
  • 為何bitmap容易造成OOM
  • 如何計算Bitmap占用內存
    • 1.1 如何計算占用內存
      • 如果圖片要顯示下Android設備上,ImageView最終是要加載Bitmap對象的,就要考慮單個Bitmap對象的內存占用了,如何計算一張圖片的加載到內存的占用呢?其實就是所有像素的內存占用總和:
      • bitmap內存大小 = 圖片長度 x 圖片寬度 x 單位像素占用的字節(jié)數(shù)
      • 起決定因素就是最后那個參數(shù)了,Bitmap'常見有2種編碼方式:ARGB_8888和RGB_565,ARGB_8888每個像素點4個byte,RGB_565是2個byte,一般都采用ARGB_8888這種。那么常見的1080*1920的圖片內存占用就是:1920 x 1080 x 4 = 7.9M
    • 1.2 上面方法計算內存對嗎
      • 我看到好多博客都是這樣計算的,但是這樣算對嗎?有沒有哥們試驗過這種方法正確性?我覺得看博客要對博主表示懷疑,論證別人寫的是否正確。更多詳細可以看我的GitHub:https://github.com/yangchong211
        • 說出我的結論:上面1.1這種說法也對,但是不全對,沒有說明場景,同時也忽略了一個影響項:Density。接下來看看源代碼。
        • inDensity默認為圖片所在文件夾對應的密度;inTargetDensity為當前系統(tǒng)密度。
        • 加載一張本地資源圖片,那么它占用的內存 = width * height * nTargetDensity/inDensity * nTargetDensity/inDensity * 一個像素所占的內存。
        @Nullablepublic static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,        @Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {    validate(opts);    if (opts == null) {        opts = new Options();    }    if (opts.inDensity == 0 && value != null) {        final int density = value.density;        if (density == TypedValue.DENSITY_DEFAULT) {            opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;        } else if (density != TypedValue.DENSITY_NONE) {            opts.inDensity = density;        }    }        if (opts.inTargetDensity == 0 && res != null) {        opts.inTargetDensity = res.getDisplayMetrics().densityDpi;    }        return decodeStream(is, pad, opts);}
      • 正確說法,這個注意呢?計算公式如下所示
        • 對資源文件:width * height * nTargetDensity/inDensity * nTargetDensity/inDensity * 一個像素所占的內存;
        • 別的:width * height * 一個像素所占的內存;
    • 1.3 一個像素占用多大內存技術博客大總結
      • Bitmap.Config用來描述圖片的像素是怎么被存儲的?
        • ARGB_8888: 每個像素4字節(jié). 共32位,默認設置。
        • Alpha_8: 只保存透明度,共8位,1字節(jié)。
        • ARGB_4444: 共16位,2字節(jié)。
        • RGB_565:共16位,2字節(jié),只存儲RGB值。

7.0.0.2 如何理解recycle釋放內存問題?圖片加載到內存其實有兩部分數(shù)據(jù),這是為何?

  • 如何理解recycle釋放內存問題?
    • 在Android2.3.3(API 10)及之前的版本中,Bitmap對象與其像素數(shù)據(jù)是分開存儲的,Bitmap對象存儲在Dalvik heap中,而Bitmap對象的像素數(shù)據(jù)則存儲在Native Memory(本地內存)中或者說Derict Memory(直接內存)中,這使得存儲在Native Memory中的像素數(shù)據(jù)的釋放是不可預知的,我們可以調用recycle()方法來對Native Memory中的像素數(shù)據(jù)進行釋放,前提是你可以清楚的確定Bitmap已不再使用了,如果你調用了Bitmap對象recycle()之后再將Bitmap繪制出來,就會出現(xiàn)”Canvas: trying to use a recycled bitmap”錯誤,而在Android3.0(API 11)之后,Bitmap的像素數(shù)據(jù)和Bitmap對象一起存儲在Dalvik heap中。
  • 圖片加載到內存其實有兩部分數(shù)據(jù),這是為何?技術博客大總結
    • 一個圖片加載到內存里,其實是有兩部分數(shù)據(jù)組成,一部分是圖片的相關描述信息,另一部分就是最重要的像素信息(這部分是有byte數(shù)組組成的),android系統(tǒng)為了提高對圖片的處理效率,對于圖片的處理都是調用了底層的功能(由C語言實現(xiàn)的),也就是說一個圖片加載到內存里后是使用兩部分的內存區(qū)域,簡單的說:一部分是java可用的內存區(qū),一部分是c可用的內存區(qū),這兩個內存區(qū)域是不能相互直接使用的,這個bitmap對象是由java分配的,當然不用的時候系統(tǒng)會自動回收了,可是那個對應的C可用的內存區(qū)域jvm是不能直接回收的,這個只能調用底層的功能釋放。所以你要調用recycle方法來釋放那一部分內存。
  • 查看源碼如下所示
    • 翻譯這段解釋:釋放bitmap內存的時候,它會釋放和這個bitmap有關的native內存,同時它會清理有關數(shù)據(jù)對象的引用,但是這里處理數(shù)據(jù)對象的引用,并不是立即清理數(shù)據(jù)(他并不是調用玩recycle()方法,就直接清理這個內存,他只是給垃圾回收機制發(fā)送一個指令,讓它在bitmap沒有對象引用的時候,來進行垃圾回收)。當調用recycle()方法之后,這個bitmap就會被表明為“死亡狀態(tài)”。這個時候你在調用bitmap其他相關的方法,例如果get像素()或set像素()就會拋出一個異常。同時這個操作是不可逆的,所以一定百分之百確定這個bitmap在以后的場景下,不會被你的程序在使用到,再去調用recycle()方法。所以谷歌源碼中建議我們,可以不用去主動調用recycle()方法,因為在沒有引用的情況下,我們的垃圾回收機制會主動的清理內存。
    • 通過看源碼,我們會發(fā)現(xiàn),這個方法首先將這個Bitmap的引用置為null,然后調用了nativeRecycle(mNativeBitMap)方法,這個方法很明顯是個JNI調用,會調用底層的c或者c 代碼就可以做到對該內存的立即回收,而不需要等待那不確定啥時候會執(zhí)行的GC來回收了。

7.0.0.3 如何在不壓縮圖片的情況下加載高清大圖?加載圖的機制是什么,為何不會內存泄漏?

  • 如何在不壓縮圖片的情況下加載高清大圖?
    • 使用BitmapRegionDecoder,主要用于顯示圖片的某一塊矩形區(qū)域,如果你需要顯示某個圖片的指定區(qū)域,那么這個類非常合適。
  • 加載圖的機制是什么,為何不會內存泄漏?
  • 自定義可拖動的顯示高清大圖的View技術博客大總結
    • 提供一個設置圖片的入口,setInputStream里面去獲得圖片的真實的寬度和高度,以及初始化我們的mDecoder
    • 重寫onTouchEvent,在里面根據(jù)用戶移動的手勢,去更新顯示區(qū)域的參數(shù)。在onMeasure里面為我們的顯示區(qū)域的rect賦值,大小為view的尺寸
    • 每次更新區(qū)域參數(shù)后,調用invalidate,onDraw里面去regionDecoder.decodeRegion拿到bitmap,然后draw。

7.0.0.7 LRU算法的原理?核心思想是什么,談談你的思路?

  • 為減少流量消耗,可采用緩存策略。常用的緩存算法是LRU(Least Recently Used):
    • 核心思想:當緩存滿時, 會優(yōu)先淘汰那些近期最少使用的緩存對象。主要是兩種方式:
      • LruCache(內存緩存):LruCache類是一個線程安全的泛型類:內部采用一個LinkedHashMap以強引用的方式存儲外界的緩存對象,并提供get和put方法來完成緩存的獲取和添加操作,當緩存滿時會移除較早使用的緩存對象,再添加新的緩存對象。
      • DiskLruCache(磁盤緩存): 通過將緩存對象寫入文件系統(tǒng)從而實現(xiàn)緩存效果
  • 大概過程如下?技術博客大總結
    • LruCache是android提供的一個緩存工具類,其算法是最近最少使用算法。它把最近使用的對象用“強引用”存儲在LinkedHashMap中,并且把最近最少使用的對象在緩存值達到預設定值之前就從內存中移除。
  • 如果緩存滿了的話,什么方法來管理移除最近最少使用的item和添加新的item?
    • trimToSize()方法,刪除最年長的條目,直到剩余條目的總數(shù)達到或低于請求的大小
      public void trimToSize(int maxSize) {    while(true) {        Object key;        Object value;        synchronized(this) {            if (this.size < 0 || this.map.isEmpty() && this.size != 0) {                throw new IllegalStateException(this.getClass().getName()   ".sizeOf() is reporting inconsistent results!");            }            if (this.size <= maxSize || this.map.isEmpty()) {                return;            }            Entry<K, V> toEvict = (Entry)this.map.entrySet().iterator().next();            key = toEvict.getKey();            value = toEvict.getValue();            this.map.remove(key);            //計算現(xiàn)在緩存的大小,然后減掉多余的,內部調用的是sizeOf()方法            this.size -= this.safeSizeOf(key, value);              this.evictionCount;        }        //如果你想在在我們的緩存中實現(xiàn)二級緩存,可以實現(xiàn)此方法,源碼中是空方法。        this.entryRemoved(true, key, value, (Object)null);    }}
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android高效加載大圖、多圖解決方案,有效避免程序OOM
Android Bitmap 全面解析(二)加載多張圖片的緩存處理
android加載大量圖片內存溢出的三種解決辦法
Android 面試題集 包含答案
圖片緩存之內存緩存技術LruCache,軟引用
淺談圖片加載的三級緩存(一)
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服