<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] 內存優化應該優先去做見效快的地方,圖片內存優化是內存優化的重點,可能一張圖片沒有回收就會造成幾M內存的浪費 # 常規的圖片內存優化方法 我們都知道,圖片所占內存=寬*高*一像素占用內存 所以優化圖片內存主要有以下幾個思路 1.縮放減小寬高 2.減少每個像素所占用的內存 3.內存復用,避免重復分配內存 4.對于大圖,可以采取局部加載的策略 ## 減少圖片寬高 有時圖片寬高為`200*200`,而`View`寬高為`100*100`,這種時候如果展示`200*200`的圖片沒有意義,應該對圖片進行縮放 這種情況一般通過`inSampleSize`實現 ~~~java BitampFactory.Options options = new BitmapFactory.Options(); // 設置為4就是寬和高都變為原來1/4大小的圖片 options.inSampleSize = 4; BitmapFactory.decodeSream(is, null, options); ~~~ ## 減少每個像素所占用的內存 在`API29`中,將`Bitmap`分為`ALPHA_8`, `RGB_565`, `ARGB_4444`, `ARGB_8888`, `RGBA_F16`, `HARDWARE`六個等級。 * `ALPHA_8`:不存儲顏色信息,每個像素占1個字節; * `RGB_565`:僅存儲`RGB`通道,每個像素占2個字節,對`Bitmap`色彩沒有高要求,可以使用該模式; * `ARGB_4444`:已棄用,用`ARGB_8888`代替; * `ARGB_8888`:每個像素占用4個字節,保持高質量的色彩保真度,默認使用該模式; * `RGBA_F16`:每個像素占用8個字節,適合寬色域和`HDR`; * `HARDWARE`:一種特殊的配置,減少了內存占用同時也加快了`Bitmap`的繪制。 每個等級每個像素所占用的字節也都不一樣,所存儲的色彩信息也不同。同一張100像素的圖片,`ARGB_8888`就占了400字節,`RGB_565`才占200字節 所以在某些場景中,修改圖片格式可以達到減少一半內存的效果 ## 內存復用,避免重復分配內存 `Bitmap`所占內存比較大,如果我們頻繁創建與回收`Bitmap`,那么很容易造成內存抖動,所以我們應該盡量復用`Bitmap`內存 在 `Android 3.0(API 級別 11)`開始,系統引入了 `BitmapFactory.Options.inBitmap` 字段。如果設置了此選項,那么采用 `Options` 對象的解碼方法會在生成目標 `Bitmap` 時嘗試復用 `inBitmap`,這意味著 `inBitmap` 的內存得到了重復使用,從而提高了性能,同時移除了內存分配和取消分配。不過 `inBitmap` 的使用方式存在某些限制,在 `Android 4.4(API 級別 19)`之前系統僅支持復用大小相同的位圖,4.4 之后只要 `inBitmap` 的大小比目標 `Bitmap` 大即可 ## 大圖局部加載策略 對于圖片加載還有種情況,就是單個圖片非常巨大,并且還不允許壓縮。比如顯示:世界地圖、清明上河圖、微博長圖等 首先不壓縮,按照原圖尺寸加載,那么屏幕肯定是不夠大的,并且考慮到內存的情況,不可能一次性整圖加載到內存中 所以這種情況的優化思路一般是局部加載,通過`BitmapRegionDecoder`來實現 ~~~java //設置顯示圖片的中心區域 BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, false); BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; Bitmap bitmap = bitmapRegionDecoder.decodeRegion(new Rect(width / 2 - 100, height / 2 - 100, width / 2 + 100, height / 2 + 100), options); mImageView.setImageBitmap(bitmap); 復制代碼 ~~~ ## 小結 上面所說的這些關于`Bitmap`的內存優化策略其實都比較簡單,而且我們在開發中可能很少用到 因為我們常用的圖片框架比如`Glide`已經將這些都封裝在里面了,所以一般情況下我們加載圖片時不需要做這些特殊操作 關于`Glide`對于加載圖片都做了哪些優化,有興趣的同學可以參考:[【帶著問題學】Glide做了哪些優化?](https://juejin.cn/post/6970683481127043085 "https://juejin.cn/post/6970683481127043085") # 圖片兜底策略 針對因`activity`、`fragment`泄漏導致的圖片泄漏,我們可以在`onDetachedFromWindow`時機進行了監控和兜底,具體流程如下: ![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3a851196e2f5439fa05070ac0c37eb90~tplv-k3u1fbpfcp-watermark.awebp) 通過這種方式可以方便地解決因`Activity`導致的圖片泄漏問題 #線上大圖監控方案 當運營在線上配置了不合理大小的圖片時,如果我們及時發現,也會帶來內存問題 如果圖片本身大小就不合理,我們在這個基礎上談圖片優化也沒有什么意義,因此大圖監控這也是個比較常見的需求 下面介紹幾種大圖監控的方案: ## `ArtHook` 方案 該方案采用`weishu`大佬寫的`epic`庫實現,通過對`ART`虛擬機的`hook`,`hook ImageView`的 `setImageBitmap` 等方法 解析對比方法參數中的 `bitmap` 寬高和 `ImageView` 實例的寬高,也可以獲得`bitmap`的實際大小 如果圖片寬高比`ImageView`寬高大,或者圖片大小超出了閾值,就可以把相關信息上報 這種方案的優點在于: 1.侵入性極低,一次初始化配置即可`hook`全局的目標`View`控件 2.可以獲取代碼調用堆棧,方便開發者快速定位 而缺點則在于: 兼容性存在問題,使用了`hook`系統`API` ,不能用于線上 ## `BaseActivity` 方案 大部分應用工程在業務發展的過程中都會沉淀封裝自己的`BaseActivity` ,通過在`BaseActivity onDestroy`中動態地檢測各個`View`控件,從而獲知圖片加載情況 ~~~kotlin class BaseActivity : Activity(){ fun onDestory(){ if(isOpenCheckBitmap){ checkBitmapFromView() } } fun checkBitmapFromView(){ //1、遍歷activity中的各個View控件 //2、獲取View控件加載的Bitmap //3、對比Bitmap寬高與View寬高 } } 復制代碼 ~~~ 這種方案的優點在于: 1.兼容性強,無任何反射 2.加入簡單,沒有什么復雜邏輯 缺點在于: 1.侵入性太強,需要修改`BaseActivity` 2.`BaseActivity.onDestory`本身可能被重寫,并不安全 ## `ASM`方案 該方案在編譯流程進行插樁,通過匹配`setImageBitmap` 、 `setBackground` 等關鍵方法,插入`Bitmap`大小檢測邏輯 這種方案優點在于: 1.編譯時期插樁,對開發過程無侵入性 缺點在于: 1.通過插樁的方式打點,可能會增加編譯期耗時 2.`ASM`代碼維護成本較高,使用起來不是那么方便 ## `registerActivityLifecycleCallback`方案 通過`registerActivityLifecycleCallback`監聽`Activity`生命周期,在`onStop`時進行`Bitmap`大小檢測的邏輯 ~~~kotlin private fun registerActivityLifecycleCallback(application: Application) { application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks { override fun onActivityStopped(activity: Activity) { checkBitmapIsTooBig(childViews) } }) } ~~~ 這種方案對原始代碼無侵入性,同時使用起來比較簡單,也沒有兼容性問題,應該屬于比較良好的方案 詳細實現可見:[BitmapCanary 誕生](https://juejin.cn/post/6956138531789996040#heading-14 "https://juejin.cn/post/6956138531789996040#heading-14") # 參考資料 [【從入門到實用】android內存優化深入解析](https://juejin.cn/post/6975876569990447134)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看