91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

五個維度:Android內存管理、優化

發布時間:2020-05-17 09:40:57 來源:網絡 閱讀:1394 作者:甲辭 欄目:移動開發


  RAM對于軟件開發環境而言是有價值的資源,但它對受限于物理內存限制的操作系統具有更大的價值。即使Android RuntimeDalvik virtual machein執行常規的垃圾回收,但這并不意味著你可以忽略app在何時何地指派和釋放內存。你仍然需要去避免產生內存泄露。比如長期持有靜態成員變量常常引起內存泄露。我們應該在合適的時間,比如在生命周期回調函數處釋放一些引用對象,來避免內存泄露的發生。

  這篇文章將闡述怎樣在app中主動的降低內存消耗。關于java編程中清理資源的一般實踐,請參照其他關于資源引用管理的書籍或者在線文檔。如果你想分析一個運行中app的內存情況,請閱讀文章“Tools for analyzing RAM usage”。如果你想知道AndroidRuntimeDalvik virtual machine如何管理內存,請參閱文章“Overview of Android Memory Management”。


(一)監控內存的使用情況:

  AndroidframeworkAndroid Studio能夠幫助你分析和調整app的內存使用情況。Android framework 暴露了幾個在app運行時動態降低內存消耗的APIAndroid Studio 提供了幾個觀察app內存使用情況的工具。


分析內存使用的工具:

  想要解決app產生的內存問題,我們首先得知道內存問題由什么引起。Android Studio提供了如下幾個分析內存的工具:

  1.MemoryMonitor展示app 在一個單獨回話過程中如何指派內存。這個工具會實時繪制包括垃圾回收事件等可用內存和已占用內存的模擬圖像。在程序運行時,你僅僅能通過初始化一個垃圾回收事件,獲取Java 堆快照。這個Memory Monitor 的輸出圖像能幫你定位到app在什么地方因產生過多的垃圾回收事件導致程序變慢。

關于Memory  Monitor的具體使用方法,請參閱“ViewingHeap Updates

  2.AllocationTracker”能夠讓我們詳細的跟蹤到app如何分配內存。這個工具能夠記錄app的內存分配情況,而且能夠列出所有被分配的對象以及分析快照。用這個工具你能夠追蹤到分配太多對象的代碼。

  關于AllocationTracker的具體使用方法,請參閱“Allocation Tracker Walkthrough


(二)在合適的時間釋放內存     

  Android設備在運行時的可用內存會根據物理內存總量以及用戶操作方法不斷變化。當系統內存有壓力的情況下會發送信號來通知程序。app應監聽這些通知,并依據監聽結果來調整內存使之使用適度。

APIComponentCallbacks2 來響應app生命周期事件 設備事件,根據監聽相關信號的結果調整內存的使用。方法onTrimMemory()能夠監聽app運行在前臺或后臺時候的相關內存事件。

Activity中,實現回調方法onTrimMemory()來監聽這些內存變化的事件,如下代碼片段:

import android.content.ComponentCallbacks2;
// Other import statements ...
publicclassMainActivityextendsAppCompatActivity
    implementsComponentCallbacks2{

    // Other activity code ...

    /**
     * Release memory when the UI becomes hidden or whensystem resources become low.
     * @param level the memory-related event that wasraised.
     */
    publicvoid onTrimMemory(int level){

        // Determine which lifecycle or systemevent was raised.
        switch(level){

            caseComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:

                /*
                  Release any UI objects that currently hold memory.

                   Theuser interface has moved to the background.
                */

                break;

            caseComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
            caseComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
            caseComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:

                /*
                  Release any memory that your app doesn't need to run.

                   Thedevice is running low on memory while the app is running.
                   Theevent raised indicates the severity of the memory-related event.
                   Ifthe event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
                   beginkilling background processes.
                */

                break;

            caseComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
            caseComponentCallbacks2.TRIM_MEMORY_MODERATE:
            caseComponentCallbacks2.TRIM_MEMORY_COMPLETE:

                /*
                  Release as much memory as the process can.

                   Theapp is on the LRU list and the system is running low on memory.
                   Theevent raised indicates where the app sits within the LRU list.
                   Ifthe event is TRIM_MEMORY_COMPLETE, the process will be one of
                   thefirst to be terminated.
                */

                break;

            default:
                /*
                  Release anynon-critical data structures.

                  The appreceived an unrecognized memory level value
                  from thesystem. Treat this as a generic low-memory message.
                */
                break;
        }
    }
} 

備注:回調方法onTrimMemory()Android4.0中添加。更早的版本,能用回調方法onLowMemory()作為替代,大約和 TRIM_MEMORY_COMPLETE 事件相同。


(三)檢查你需要用到的內存:

  為了支持多進程,android為每一個app設置了一個堆內存上限。不同設備為app分配的具體上限值,取決于RAM的總大小。如果程序到達了這個上限值還想占用更多的內存,系統將會拋出異常 OutOfMemoryError

  為了避免內存溢出,我們可以查詢當前設備為app指定的內存上限值。我們可以通過調用方法getMemoryInfo()來查詢當前系統的這個屬性值。這個方法將會返回一個包含可用內存、總內存、內存臨界值(如果系統可用內存低于這個臨界值將會殺掉部分進程)等當前設備狀態的ActivityManager.MemoryInfo對象。ActivityManager.MemoryInfo也提供了一個boolean類型的字段lowMemory,記錄當前設備是否運行在低內存情況下。

下面的代碼片段展示了一個使用geMemoryInfo()方法的例子:

public void doSomethingMemoryIntensive(){


   
// Before doing something that requires a lot of memory,
   
// check to see whether the device is in a low memory state.
   
ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();

   
if(!memoryInfo.lowMemory){
       
// Do memory intensive work ...
   
}
}

// Get a MemoryInfo object for the device's current memory status.
privateActivityManager.MemoryInfo getAvailableMemory(){
   
ActivityManager activityManager =(ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
   
ActivityManager.MemoryInfo memoryInfo =newActivityManager.MemoryInfo();
    activityManager
.getMemoryInfo(memoryInfo);
   
return memoryInfo;
}

(四)使用高效內存的代碼結構

    一些android特性、java類、代碼結構趨向于用更多的內存。我們可以通過選擇更高效的替代方案來使我們app用最少的內存。

 

(1)少用Services

 在不必要的時候運行一個服務,是app最糟糕的內存管理錯誤之一。如果app需要運行一個服務在后臺執行工作,除非有必要的任務,否則不要一直運行。當Service完成它的任務后一定要記得停這個Service。否則,可能一不留神就產生一個內存泄露。

 開啟一個Service后,系統喜歡為這個service開啟一個進程使其持續運行。這種情況使Service非常耗費資源,因為其他進程無法使用被service所在進程占用的RAM資源。系統緩存在LRU catche的進程數量減少后,使app運行效率降低。更有甚者,當內存緊張,系統無法維持足夠的進程支持所有service的時候,service可能被銷毀。

 通常情況下我們應該避免長期使用service,因為它們會一直占用內存。我們推薦使用可供選擇的類比如JobScheduler 去調度后臺進程。

 關于如何使用JobScheduler調度后臺進程,參閱“BackgroundOptimizations


(2)使用最優化的數據容器:

  編程語言提供的部分類對于移動設備不是最優化的。例如一般的HashMap實現能使很多內存低效率工作,因為它需要為每一個映射生成一個單獨的條目對象。

Androidframework包含幾個最優化的數據容器,包括SparseArraySparseBooleanArrayLongSparseArray。例如 AparseArray之所以更高效,是由于它們避免系統的需要,對key(有時候也對value)進行自動裝箱。

如果有必要,我們可以總是選擇原始的數組作為最精煉的數據結構。

(3)謹慎使用抽象代碼:

  開發者通常僅僅把抽象當成一種好的編程實踐,因為抽象可以提升代碼的靈活性和可維護性。然而,抽象伴隨著巨大的資源耗費而來:通常它們會需要更多的時間和更多的內存,需要執行相當數量的代碼,花費更多的時間和內存。所以如果抽象不能帶來巨大好處,我們應該盡可能去避免。

例如:枚舉需要消耗的內存通常是靜態變量的兩倍多。我們應該嚴格避免在android上使用枚舉。

(4)使用nanoprotobufs序列化數據

    Protocol buffers 是一個谷歌設計的具有語言中立、平臺中立、可擴展、用來序列化結構數據的類似于XML的機制,但其比XML快,比XML小,比XML簡單。如果你決定使用protobufs處理數據,那么我們應該在客戶端代碼中一直使用nano protobufs。普通的protobufs通常生成非常多的代碼,這樣會引起app產生很多問題,比如占用更多內存、APK尺寸大幅度增加、運行緩慢。

更多運行,請參閱文章"protobuf readme""Nanoversion"的段落。

 

(5)避免內存抖動

  就像上文提醒到的,GC事件通常不會影響app的性能。然而一些發生在短時間內的GC事件能迅速耗盡你的幀像時間。系統花費在GC上的時間越多,那么它處理其他諸如渲染或者音頻流的事件。

  通常情況下下,內存抖動能引起大量的的GC事件。在實踐中,內存抖動描繪的是,在一個給定時間內,分配臨時對象的數目。

  例如,你可能通過for循環分配多個臨時對象。或者在一個ViewonDraw方法中創建一個Paint或者Bitmap對象。如上兩個例子,app迅速地創建了大量的大體積對象。年青一代的這些行為將會迅速的消耗所有的可用內存,強制一個垃圾回收事件產生。

  當然,在你修復內存抖動之前,需要先發現導致內存抖動發生的代碼所在地方。請用在文章"Analyze your RAM usage"中討論的工具。

  一旦你識別代碼出現問題的區域,試著降低處于性能臨界區域的配置數目。考慮移除內循環的東西,或者將它們移到基于分配結構的 Factory(參閱文章:)。

 

(五)降低內存占有量——累贅的資源和庫


  一些資源和庫在你的代碼能在你不知道的情況下貪婪的消耗內存。apk的大小、包括第三方庫以及嵌入的資源、能夠影響app消耗的內存量。我們能通過移除代碼中多余的、不必要的、臃腫的組件、資源或者庫的方式來改善app的內存消耗。


(1)降低apk大小

  我們能通過降低apk大小的方式顯著的降低app的內存使用情況。bitmap尺寸、資源、動畫的幀、第三方庫都能導致apk變大。android sdk android studio 提供了多種工具來幫助我們降低資源和外部依賴的尺寸。

  關于降低apk大小的更多信息,參閱"ReduceAPK Size"

(2)如果需要依賴注入,建議使用Dagger

  依賴注入框架能夠簡化你寫的代碼以及為測試和測試改變提供一個適配的環境。如果你打算在app中用一個依賴注入框架,考慮使用Dagger2(參閱https://google.github.io/dagger/.

Dagger不會用反射掃描app代碼。它是靜態的、編譯時實現的框架,這意味著在運行時沒有不必要的運行時花費或者內存使用。

  其他的那些依賴注入框架通過掃描代碼和注解,運用反射去初始化進程。這個產生的進程會需要大量的CPU周期以及內存,能在app啟動時引起一個顯而易見的延遲。

 

(3)謹慎使用依賴庫:

  外部庫的代碼通常不是為手機環境所寫,使其在手機客戶端上工作時可能是很低效的。當我們決定用一個依賴庫,可能需要針對移動設備進行優化。在決定真正使用這個依賴庫之前,應預先做好針對移動設備優化的計劃,依據代碼尺寸和內存大小進行分析。

  即使一些移動優化的庫也能由于不同的實現引起問題。例如,當一個庫使用了micro protobufs而一個庫使用了nano protobufs,這樣app中有兩個不同的 protobuf實現。當問題發生時,原因可能是logginganalyticsp_w_picpath loading frameworkscaching或者一些其他我們無法預料的事情的不同實現導致的。

  盡管ProGuard(參閱:https://developer.android.com/studio/build/shrink-code.html)能根據正確的標記移除APIs和資源,但是它不能移除一個庫大型的依賴。你在庫中想要的特性可能需要低版本的依賴....

  翻譯整理,更多內容,敬請期待....

         


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

余姚市| 浏阳市| 鸡泽县| 青浦区| 手机| 卢龙县| 汉川市| 阜阳市| 沽源县| 康平县| 南华县| 九江市| 汉源县| 尚义县| 文成县| 临桂县| 芒康县| 崇信县| 河东区| 天祝| 左权县| 新余市| 常宁市| 祁门县| 鄂托克旗| 章丘市| 偏关县| 阿勒泰市| 麟游县| 米易县| 依兰县| 甘孜| 犍为县| 翁牛特旗| 长阳| 中卫市| 铅山县| 安多县| 巢湖市| 绥宁县| 延庆县|