<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          優(yōu)化App內(nèi)存方法知多少

          共 7089字,需瀏覽 15分鐘

           ·

          2021-01-14 23:50

          和你一起終身學(xué)習(xí),這里是程序員Android

          經(jīng)典好文推薦,通過閱讀本文,您將收獲以下知識點(diǎn):

          一、App內(nèi)存優(yōu)化概述
          二、監(jiān)視可用內(nèi)存和內(nèi)存使用情況
          三、合理的釋放內(nèi)存
          四、分析App需要用多少內(nèi)存
          五、使用內(nèi)存優(yōu)化框架
          六、移除內(nèi)存密集型資源,以及l(fā)ib庫

          一、App內(nèi)存優(yōu)化概述

          隨機(jī)存取存儲器(RAM)在任何軟件開發(fā)環(huán)境中都是非常有價(jià)值的資源,但對于物理內(nèi)存經(jīng)常受到限制的移動操作系統(tǒng)來說,它更有價(jià)值。盡管Android運(yùn)行時(shí)(ART)和Dalvik虛擬機(jī)都執(zhí)行常規(guī)垃圾收集,但這并不意味著您可以忽略應(yīng)用程序分配和釋放內(nèi)存的時(shí)間和位置。您仍然需要避免引入內(nèi)存泄漏,這些通常由靜態(tài)成員變量中的對象引用引起,并在生命周期回調(diào)定義的適當(dāng)時(shí)間釋放任何引用對象。

          本頁面介紹了如何主動減少應(yīng)用程序中的內(nèi)存使用量。有關(guān)Android操作系統(tǒng)如何管理內(nèi)存的信息,請參閱Android內(nèi)存管理概述

          二、監(jiān)視可用內(nèi)存和內(nèi)存使用情況

          在修復(fù)解決APP 中的內(nèi)存使用問題之前,首先需要找到它們。 Android Studio中的內(nèi)存分析器Memory Profiler可以幫助您通過以下方式查找和診斷內(nèi)存問題:

          1 . 查看App如何分配內(nèi)存。

          Memory Profiler顯示了一個(gè)實(shí)時(shí)圖,顯示您的應(yīng)用程序使用了多少內(nèi)存,分配了Java對象的數(shù)量以及何時(shí)發(fā)生垃圾回收。

          2. 記錄GC快照

          啟動垃圾收集事件并在運(yùn)行應(yīng)用程序時(shí)抓取Java堆的快照。

          3.記錄您的應(yīng)用程序的內(nèi)存分配

          然后檢查所有分配的對象,查看每個(gè)分配的堆棧跟蹤,然后跳轉(zhuǎn)到Android Studio編輯器中的相應(yīng)代碼。

          三、合理的釋放內(nèi)存

          Android可以通過多種方式從您的應(yīng)用程序中回收內(nèi)存,或者在必要時(shí)將應(yīng)用程序徹底關(guān)閉以釋放內(nèi)存以用于關(guān)鍵任務(wù)。為了進(jìn)一步幫助平衡系統(tǒng)內(nèi)存,避免系統(tǒng)需要終止應(yīng)用程序進(jìn)程,可以在Activity類中實(shí)現(xiàn)ComponentCallbacks2接口提供的onTrimMemory()回調(diào)方法,從而允許您的應(yīng)用程序在處于前臺或后臺時(shí)偵聽與內(nèi)存相關(guān)的事件,然后釋放對象以響應(yīng)應(yīng)用程序生命周期,或者指示系統(tǒng)需要回收內(nèi)存的系統(tǒng)事件。

          例如,您可以實(shí)現(xiàn)onTrimMemory()回調(diào)以響應(yīng)不同的內(nèi)存相關(guān)事件,如下所示:

          import android.content.ComponentCallbacks2;
          // Other import statements ...

          public class MainActivity extends AppCompatActivity
          implements ComponentCallbacks2 {

          // Other activity code ...

          /**
          * Release memory when the UI becomes hidden or when system resources become low.
          * @param level the memory-related event that was raised.
          */

          public void onTrimMemory(int level) {

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

          case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:

          /*
          Release any UI objects that currently hold memory.

          The user interface has moved to the background.
          */


          break;

          case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
          case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
          case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:

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

          The device is running low on memory while the app is running.
          The event raised indicates the severity of the memory-related event.
          If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
          begin killing background processes.
          */


          break;

          case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
          case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
          case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:

          /*
          Release as much memory as the process can.

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


          break;

          default:
          /*
          Release any non-critical data structures.

          The app received an unrecognized memory level value
          from the system. Treat this as a generic low-memory message.
          */

          break;
          }
          }
          }

          onTrimMemory() 回調(diào)方法是在Android 4.0時(shí)候添加的,之前版本請用onLowMemory()方法,跟TRIM_MEMORY_COMPLETE事件處理一樣。

          四、分析App需要用多少內(nèi)存

          為了允許多個(gè)正在運(yùn)行的進(jìn)程,Android為每個(gè)應(yīng)用程序分配的堆大小設(shè)置了硬限制。確切的堆大小限制根據(jù)設(shè)備有多少總體可用RAM不同而有所不同。如果您的應(yīng)用程序已達(dá)到堆容量并嘗試分配更多內(nèi)存,則系統(tǒng)將引發(fā)OutOfMemoryError。

          為了避免OutOfMemoryError內(nèi)存不足,可以查詢系統(tǒng)以確定當(dāng)前設(shè)備上有多少可用的堆空間。你可以通過調(diào)用getMemoryInfo()來查詢這個(gè)數(shù)字。這將返回一個(gè)ActivityManager.MemoryInfo對象,該對象提供有關(guān)設(shè)備當(dāng)前內(nèi)存狀態(tài)的信息,包括可用內(nèi)存,總內(nèi)存以及內(nèi)存閾值(即系統(tǒng)開始中斷進(jìn)程的內(nèi)存級別)。 ActivityManager.MemoryInfo對象還暴露了一個(gè)簡單的布爾值,lowMemory,可以判斷你設(shè)備是否在低內(nèi)存下運(yùn)行。

          如下例子,舉例使用getMemoryInfo()

          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.
          private ActivityManager.MemoryInfo getAvailableMemory() {
          ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
          ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
          activityManager.getMemoryInfo(memoryInfo);
          return memoryInfo;
          }

          五、使用內(nèi)存優(yōu)化框架

          一些Android功能,Java類和代碼構(gòu)造傾向于使用比其他更多的內(nèi)存。您可以通過在代碼中選擇更有效的替代方法來最大限度地減少應(yīng)用程序使用的內(nèi)存量

          1. 謹(jǐn)慎使用Services

          在不需要Services的情況下運(yùn)行Services,是造成最嚴(yán)重的內(nèi)存管理錯(cuò)誤之一。
          如果你的應(yīng)用程序需要一個(gè)Services來在后臺執(zhí)行工作,那么除非它需要運(yùn)行一個(gè)后臺任務(wù),否則不要讓它保持運(yùn)行。記得在完成任務(wù)時(shí)停止Services。否則,您可能會無意中造成內(nèi)存泄漏。
          當(dāng)你啟動一個(gè)Services時(shí), 系統(tǒng)需要始終保持運(yùn)行該Services的進(jìn)程。此行為使得Services進(jìn)程非常昂貴,因?yàn)镾ervices使用的RAM對其他進(jìn)程仍然不可用。這樣可以減少系統(tǒng)在LRU緩存中保留的緩存進(jìn)程的數(shù)量,從而降低應(yīng)用程序切換的效率。內(nèi)存不足時(shí)系統(tǒng)甚至可能導(dǎo)致系統(tǒng)崩潰,系統(tǒng)無法維護(hù)足夠的進(jìn)程來承載當(dāng)前運(yùn)行的所有服務(wù)。

          您通常應(yīng)該避免使用持久性Persistent Services,因?yàn)檫@些服務(wù)會常駐系統(tǒng)內(nèi)存。相反,我們建議您使用諸如JobScheduler之類的替代實(shí)現(xiàn)。有關(guān)如何使用JobScheduler安排后臺進(jìn)程的更多信息,請參閱后臺優(yōu)化。

          如果您必須使用服務(wù),那么限制服務(wù)使用壽命的最好方法就是使用IntentService,一旦完成了處理啟動它的意圖,IntentService就會自動完成。有關(guān)更多信息,請閱讀在后臺服務(wù)中運(yùn)行。

          2.使用更優(yōu)化的數(shù)據(jù)容器

          編程語言提供的某些類未針對在移動設(shè)備上使用進(jìn)行優(yōu)化。例如,通用的HashMap實(shí)現(xiàn)可能是相當(dāng)?shù)托У膬?nèi)存,因?yàn)槊總€(gè)映射都需要單獨(dú)的入口對象。

          Android框架包括幾個(gè)優(yōu)化的數(shù)據(jù)容器,包括SparseArray,SparseBooleanArrayLongSparseArray。例如,SparseArray類更有效率,因?yàn)樗鼈儽苊饬讼到y(tǒng)需要自動復(fù)制密鑰的情況,有時(shí)還需要創(chuàng)建另外一個(gè)或兩個(gè)對象。

          如有必要,您可以隨時(shí)切換到原始數(shù)組以獲得精簡的數(shù)據(jù)結(jié)構(gòu)。

          3.使用nano protobufs進(jìn)行序列化數(shù)據(jù)

          協(xié)議緩沖區(qū)是一種語言中立,平臺無關(guān),可擴(kuò)展的機(jī)制,由Google設(shè)計(jì),用于序列化結(jié)構(gòu)化數(shù)據(jù) - 類似于XML,但更小,更快,更簡單。如果你決定為你的數(shù)據(jù)使用protobufs,你應(yīng)該總是在你的客戶端代碼中使用nano protobufs。經(jīng)常protobufs生成非常詳細(xì)的代碼,這可能會導(dǎo)致您的應(yīng)用程序中的許多種問題,如增加的RAM使用,APK大小增加,和較慢的執(zhí)行。

          有關(guān)更多信息,請參閱protobuf自述文件中的“Nano版本”部分。

          4.避免內(nèi)存泄漏

          如前所述,垃圾收集事件通常不會影響您的應(yīng)用程序的性能。但是,很多短時(shí)間內(nèi)發(fā)生的垃圾收集事件可能會很快消耗掉你的幀時(shí)間。系統(tǒng)花費(fèi)在垃圾收集上的時(shí)間越多,執(zhí)行其他內(nèi)容(如渲染或流式傳輸音頻)的時(shí)間就越少。

          內(nèi)存流失通常會導(dǎo)致大量的垃圾收集事件發(fā)生。在實(shí)踐中,內(nèi)存流失描述了在給定的時(shí)間內(nèi)發(fā)生的分配的臨時(shí)對象的數(shù)量。

          例如,您可以在for循環(huán)中分配多個(gè)臨時(shí)對象?;蛘吣梢栽谝晥D的onDraw()函數(shù)內(nèi)創(chuàng)建新的PaintBitmap對象。在這兩種情況下,應(yīng)用程序都會以大批量快速創(chuàng)建大量對象。這些可能會迅速消耗年輕一代中的所有可用內(nèi)存,從而迫使垃圾收集事件發(fā)生。

          當(dāng)然,你需要在你的代碼中找到內(nèi)存流失高的地方,然后才能修復(fù)它們。為此,您應(yīng)該在Android Studio中使用Memory Profiler

          六、移除內(nèi)存密集型資源,以及l(fā)ib庫

          你的代碼中的一些資源和庫可以在你不知道的情況下吞噬內(nèi)存。您的APK的整體大?。òǖ谌綆旎蚯度胧劫Y源)可能會影響您的應(yīng)用消耗的內(nèi)存量。您可以通過從代碼中刪除冗余,不必要或臃腫的組件,資源或庫來改善應(yīng)用程序的內(nèi)存消耗。

          1.減小APK的大小

          您可以通過減少應(yīng)用程序的整體大小來顯著減少應(yīng)用程序的內(nèi)存使用量。比如:bitmap大小,res資源,動畫幀數(shù)以及第三方庫都可以影響APK的大小。 Android StudioAndroid SDK提供了多種工具來幫助您減少資源和外部依賴的大小。

          有關(guān)如何減少您的整體APK大小的更多信息,請參閱縮小APK大小。

          2.使用Dagger 2進(jìn)行依賴注入

          依賴注入框架可以簡化您編寫的代碼,并提供適用于測試和其他配置更改的自適應(yīng)環(huán)境。

          如果您打算在應(yīng)用程序中使用依賴項(xiàng)注入框架,請考慮使用Dagger 2Dagger 2不使用反射來掃描您的應(yīng)用程序的代碼。Dagger的靜態(tài)編譯實(shí)現(xiàn),意味著它可以在Android應(yīng)用程序中使用,而無需增加運(yùn)行成本或內(nèi)存使用。

          其他使用反射的依賴注入框架傾向于通過掃描代碼來注釋來初始化進(jìn)程。這個(gè)過程可能需要更多的CPU周期和內(nèi)存,并且在應(yīng)用程序啟動時(shí)會引起明顯的滯后。

          3.謹(jǐn)慎使用外部庫

          外部庫代碼通常不是針對移動環(huán)境編寫的,而且在用于移動客戶端時(shí)可能效率低下。當(dāng)您決定使用外部庫時(shí),您可能需要為移動設(shè)備優(yōu)化該庫。預(yù)先計(jì)劃好這個(gè)工作,然后根據(jù)代碼大小和內(nèi)存占用情況來分析這個(gè)庫,然后才決定使用它。

          即使一些移動優(yōu)化的庫可能由于不同的實(shí)現(xiàn)而導(dǎo)致問題。例如,一個(gè)庫可能使用nano protobufs,而另一個(gè)庫使用微型protobufs,導(dǎo)致您的應(yīng)用程序中有兩個(gè)不同的protobuf實(shí)現(xiàn)。這可能發(fā)生在不同的日志記錄,分析,圖像加載框架,緩存以及許多您不希望的事情上。

          盡管ProGuard可以幫助您使用正確的標(biāo)志刪除API和資源,但它不能刪除庫的大型內(nèi)部依賴關(guān)系。您需要在這些庫中的功能可能需要較低級別的依賴關(guān)系。如果庫使用反射,這是常見的,并且意味著您需要花費(fèi)大量時(shí)間手動調(diào)整ProGuard才能使用反射,那么當(dāng)您從庫中使用Activity子類時(shí),這往往會產(chǎn)生大量的依賴關(guān)系工作等等。

          至此,本篇已結(jié)束。轉(zhuǎn)載網(wǎng)絡(luò)的文章,小編覺得很優(yōu)秀,歡迎點(diǎn)擊閱讀原文,支持原創(chuàng)作者,如有侵權(quán),懇請聯(lián)系小編刪除。同時(shí)感謝您的閱讀,期待您的關(guān)注。

          點(diǎn)個(gè)在看,方便您使用時(shí)快速查找!

          瀏覽 51
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爆操逼逼| 高潮喷水在线观看 | 日韩人妻久久 | 亚洲成人综合最新 | 美日韩一级黄色片 |