日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android最佳性能实践(一)——合理管理内存

發布時間:2024/3/7 Android 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android最佳性能实践(一)——合理管理内存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請注明出處:http://blog.csdn.net/guolin_blog/article/details/42238627

有不少朋友都問過我,怎樣才能寫出高性能的應用程序,如何避免程序出現OOM,或者當程序內存占用過高的時候該怎么樣去排查。確實,一個優秀的應用程序,不僅僅要功能完成得好,性能問題也應該處理得恰到好處。為此,我也是閱讀了不少Android官方給出的高性能編程建議,那么從本篇文章開始,我就準備開始寫一個全新系列的博文,來把這些建議進行整理和分析,幫助大家能夠寫出更加出色的應用程序。

注意本系列文章的內容基本源于Android Doc,如果想要閱讀更加詳細的關于性能方面的資料,可以直接去閱讀Android官方文檔。

內存(RAM)對于任何一個軟件開發環境都是種非常珍貴的資源,而對于移動操作系統來講的話,則會顯得更加珍貴,因為手機的硬件條件相對于PC畢竟是比較落后的。盡管Android系統的虛擬機擁有自動回收垃圾的機制,但這并不代表我們就可以忽視應該在什么時候分配和釋放內存。

為了使垃圾回收器可以正常釋放程序所占用的內存,在編寫代碼的時候就一定要注意盡量避免出現內存泄漏的情況(通常都是由于全局成員變量持有對象引用所導致的),并且在適當的時候去釋放對象引用。對于大多數的應用程序而言,后面其它的事情就可以都交給垃圾回收器去完成了,如果一個對象的引用不再被其它對象所持有,那么系統就會將這個對象所分配的內存進行回收。

我們在開發軟件的時候應當自始至終都把內存的問題充分考慮進去,這樣的話才能開發出更加高性能的軟件。而內存問題也并不是無規律可行的,Android系統給我們提出了很多內存優化的建議技巧,只要按照這些技巧來編寫程序,就可以讓我們的程序在內存性能發面表現得相當不錯,下面我們就來一一學習一下這些技巧。

節制地使用Service

如果應用程序當中需要使用Service來執行后臺任務的話,請一定要注意只有當任務正在執行的時候才應該讓Service運行起來。另外,當任務執行完之后去停止Service的時候,要小心Service停止失敗導致內存泄漏的情況。

當我們啟動一個Service時,系統會傾向于將這個Service所依賴的進程進行保留,這樣就會導致這個進程變得非常消耗內存。并且,系統可以在LRU cache當中緩存的進程數量也會減少,導致切換應用程序的時候耗費更多性能。嚴重的話,甚至有可能會導致崩潰,因為系統在內存非常吃緊的時候可能已無法維護所有正在運行的Service所依賴的進程了。

為了能夠控制Service的生命周期,Android官方推薦的最佳解決方案就是使用IntentService,這種Service的最大特點就是當后臺任務執行結束后會自動停止,從而極大程度上避免了Service內存泄漏的可能性。關于IntentService更加詳細的用法講解,可以參考《第一行代碼——Android》的9.5.2節。

讓一個Service在后臺一直保持運行,即使它并不執行任何工作,這是編寫Android程序時最糟糕的做法之一。所以Android官方極度建議開發人員們不要過于貪婪,讓Service在后臺一直運行,這不僅可能會導致手機和程序的性能非常低下,而且被用戶發現了之后也有可能直接導致我們的軟件被卸載(我個人就會這么做)。

當界面不可見時釋放內存

當用戶打開了另外一個程序,我們的程序界面已經不再可見的時候,我們應當將所有和界面相關的資源進行釋放。在這種場景下釋放資源可以讓系統緩存后臺進程的能力顯著增加,因此也會讓用戶體驗變得更好。

那么我們如何才能知道程序界面是不是已經不可見了呢?其實很簡單,只需要在Activity中重寫onTrimMemory()方法,然后在這個方法中監聽TRIM_MEMORY_UI_HIDDEN這個級別,一旦觸發了之后就說明用戶已經離開了我們的程序,那么此時就可以進行資源釋放操作了,如下所示:

[java]?view plaincopy
  • @Override??
  • public?void?onTrimMemory(int?level)?{??
  • ????super.onTrimMemory(level);??
  • ????switch?(level)?{??
  • ????case?TRIM_MEMORY_UI_HIDDEN:??
  • ????????//?進行資源釋放操作??
  • ????????break;??
  • ????}??
  • }??
  • 注意onTrimMemory()方法中的TRIM_MEMORY_UI_HIDDEN回調只有當我們程序中的所有UI組件全部不可見的時候才會觸發,這和onStop()方法還是有很大區別的,因為onStop()方法只是當一個Activity完全不可見的時候就會調用,比如說用戶打開了我們程序中的另一個Activity。因此,我們可以在onStop()方法中去釋放一些Activity相關的資源,比如說取消網絡連接或者注銷廣播接收器等,但是像UI相關的資源應該一直要等到onTrimMemory(TRIM_MEMORY_UI_HIDDEN)這個回調之后才去釋放,這樣可以保證如果用戶只是從我們程序的一個Activity回到了另外一個Activity,界面相關的資源都不需要重新加載,從而提升響應速度。

    當內存緊張時釋放內存

    除了剛才講的TRIM_MEMORY_UI_HIDDEN這個回調,onTrimMemory()方法還有很多種其它類型的回調,可以在手機內存降低的時候及時通知我們。我們應該根據回調中傳入的級別來去決定如何釋放應用程序的資源:

    • TRIM_MEMORY_RUNNING_MODERATE ? ?表示應用程序正常運行,并且不會被殺掉。但是目前手機的內存已經有點低了,系統可能會開始根據LRU緩存規則來去殺死進程了。
    • TRIM_MEMORY_RUNNING_LOW ? ?表示應用程序正常運行,并且不會被殺掉。但是目前手機的內存已經非常低了,我們應該去釋放掉一些不必要的資源以提升系統的性能,同時這也會直接影響到我們應用程序的性能。
    • TRIM_MEMORY_RUNNING_CRITICAL ? ?表示應用程序仍然正常運行,但是系統已經根據LRU緩存規則殺掉了大部分緩存的進程了。這個時候我們應當盡可能地去釋放任何不必要的資源,不然的話系統可能會繼續殺掉所有緩存中的進程,并且開始殺掉一些本來應當保持運行的進程,比如說后臺運行的服務。

    以上是當我們的應用程序正在運行時的回調,那么如果我們的程序目前是被緩存的,則會收到以下幾種類型的回調:

    • TRIM_MEMORY_BACKGROUND ? ?表示手機目前內存已經很低了,系統準備開始根據LRU緩存來清理進程。這個時候我們的程序在LRU緩存列表的最近位置,是不太可能被清理掉的,但這時去釋放掉一些比較容易恢復的資源能夠讓手機的內存變得比較充足,從而讓我們的程序更長時間地保留在緩存當中,這樣當用戶返回我們的程序時會感覺非常順暢,而不是經歷了一次重新啟動的過程。
    • TRIM_MEMORY_MODERATE ? ?表示手機目前內存已經很低了,并且我們的程序處于LRU緩存列表的中間位置,如果手機內存還得不到進一步釋放的話,那么我們的程序就有被系統殺掉的風險了。
    • TRIM_MEMORY_COMPLETE ? ?表示手機目前內存已經很低了,并且我們的程序處于LRU緩存列表的最邊緣位置,系統會最優先考慮殺掉我們的應用程序,在這個時候應當盡可能地把一切可以釋放的東西都進行釋放。

    避免在Bitmap上浪費內存

    當我們讀取一個Bitmap圖片的時候,有一點一定要注意,就是千萬不要去加載不需要的分辨率。在一個很小的ImageView上顯示一張高分辨率的圖片不會帶來任何視覺上的好處,但卻會占用我們相當多寶貴的內存。需要僅記的一點是,將一張圖片解析成一個Bitmap對象時所占用的內存并不是這個圖片在硬盤中的大小,可能一張圖片只有100k你覺得它并不大,但是讀取到內存當中是按照像素點來算的,比如這張圖片是1500*1000像素,使用的ARGB_8888顏色類型,那么每個像素點就會占用4個字節,總內存就是1500*1000*4字節,也就是5.7M,這個數據看起來就比較恐怖了。

    至于如何去壓縮圖片,以及更多在圖片方面節省內存的技術,大家可以去參考我之前寫的一篇博客?Android高效加載大圖、多圖解決方案,有效避免程序OOM?。

    使用優化過的數據集合

    Android API當中提供了一些優化過后的數據集合工具類,如SparseArray,SparseBooleanArray,以及LongSparseArray等,使用這些API可以讓我們的程序更加高效。傳統Java API中提供的HashMap工具類會相對比較低效,因為它需要為每一個鍵值對都提供一個對象入口,而SparseArray就避免掉了基本數據類型轉換成對象數據類型的時間。

    知曉內存的開支情況

    我們還應當清楚我們所使用語言的內存開支和消耗情況,并且在整個軟件的設計和開發當中都應該將這些信息考慮在內。可能有一些看起來無關痛癢的寫法,結果卻會導致很大一部分的內存開支,例如:

    • 使用枚舉通常會比使用靜態常量要消耗兩倍以上的內存,在Android開發當中我們應當盡可能地不使用枚舉。
    • 任何一個Java類,包括內部類、匿名類,都要占用大概500字節的內存空間。
    • 任何一個類的實例要消耗12-16字節的內存開支,因此頻繁創建實例也是會一定程序上影響內存的。
    • 在使用HashMap時,即使你只設置了一個基本數據類型的鍵,比如說int,但是也會按照對象的大小來分配內存,大概是32字節,而不是4字節。因此最好的辦法就是像上面所說的一樣,使用優化過的數據集合。

    謹慎使用抽象編程

    許多程序員都喜歡各種使用抽象來編程,認為這是一種很好的編程習慣。當然,這一點不可否認,因為的抽象的編程方法更加面向對象,而且在代碼的維護和可擴展性方面都會有所提高。但是,在Android上使用抽象會帶來額外的內存開支,因為抽象的編程方法需要編寫額外的代碼,雖然這些代碼根本執行不到,但是卻也要映射到內存當中,不僅占用了更多的內存,在執行效率方面也會有所降低。當然這里我并不是提倡大家完全不使用抽象編程,而是謹慎使用抽象編程,不要認為這是一種很酷的編程方式而去肆意使用它,只在你認為有必要的情況下才去使用。

    盡量避免使用依賴注入框架

    現在有很多人都喜歡在Android工程當中使用依賴注入框架,比如說像Guice或者RoboGuice等,因為它們可以簡化一些復雜的編碼操作,比如可以將下面的一段代碼:

    [java]?view plaincopy
  • class?AndroidWay?extends?Activity?{???
  • ????TextView?name;???
  • ????ImageView?thumbnail;???
  • ????LocationManager?loc;???
  • ????Drawable?icon;???
  • ????String?myName;???
  • ??
  • ????public?void?onCreate(Bundle?savedInstanceState)?{???
  • ????????super.onCreate(savedInstanceState);???
  • ????????setContentView(R.layout.main);??
  • ????????name??????=?(TextView)?findViewById(R.id.name);???
  • ????????thumbnail?=?(ImageView)?findViewById(R.id.thumbnail);???
  • ????????loc???????=?(LocationManager)?getSystemService(Activity.LOCATION_SERVICE);???
  • ????????icon??????=?getResources().getDrawable(R.drawable.icon);???
  • ????????myName????=?getString(R.string.app_name);???
  • ????????name.setText(?"Hello,?"?+?myName?);???
  • ????}???
  • }???
  • 簡化成這樣的一種寫法: [java]?view plaincopy
  • @ContentView(R.layout.main)??
  • class?RoboWay?extends?RoboActivity?{???
  • ????@InjectView(R.id.name)?????????????TextView?name;???
  • ????@InjectView(R.id.thumbnail)????????ImageView?thumbnail;???
  • ????@InjectResource(R.drawable.icon)???Drawable?icon;???
  • ????@InjectResource(R.string.app_name)?String?myName;???
  • ????@Inject????????????????????????????LocationManager?loc;???
  • ??
  • ????public?void?onCreate(Bundle?savedInstanceState)?{???
  • ????????super.onCreate(savedInstanceState);???
  • ????????name.setText(?"Hello,?"?+?myName?);???
  • ????}???
  • }??
  • 看上去確實十分誘人,我們甚至可以將findViewById()這一類的繁瑣操作全部省去了。但是這些框架為了要搜尋代碼中的注解,通常都需要經歷較長的初始化過程,并且還可能將一些你用不到的對象也一并加載到內存當中。這些用不到的對象會一直占用著內存空間,可能要過很久之后才會得到釋放,相較之下,也許多敲幾行看似繁瑣的代碼才是更好的選擇。

    使用ProGuard簡化代碼

    ProGuard相信大家都不會陌生,很多人都會使用這個工具來混淆代碼,但是除了混淆之外,它還具有壓縮和優化代碼的功能。ProGuard會對我們的代碼進行檢索,刪除一些無用的代碼,并且會對類、字段、方法等進行重命名,重命名之后的類、字段和方法名都會比原來簡短很多,這樣的話也就對內存的占用變得更少了。

    使用多個進程

    這個技巧其實并不是非常建議使用,但它確實是一種可以幫助我們節省和管理內存的高級技巧。如果你要使用它的話一定要謹慎使用,因為絕大多數的應用程序都不應該在多個進程當中運行的,一旦使用不當,它甚至會增加額外的內存而不是幫我們節省內存。這個技巧比較適用于那些需要在后臺去完成一項獨立的任務,和前臺的功能是可以完全區分開的場景。

    這里舉一個比較適合去使用多進程技巧的場景,比如說我們正在做一個音樂播放器軟件,其中播放音樂的功能應該是一個獨立的功能,它不需要和UI方面有任何關系,即使軟件已經關閉了也應該可以正常播放音樂。如果此時我們只使用一個進程,那么即使用戶關閉了軟件,已經完全由Service來控制音樂播放了,系統仍然會將許多UI方面的內存進行保留。在這種場景下就非常適合使用兩個進程,一個用于UI展示,另一個則用于在后臺持續地播放音樂。

    想要實現多進程的功能也非常簡單,只需要在AndroidManifest文件的應用程序組件中聲明一個android:process屬性就可以了,比如說我們希望播放音樂的Service可以運行在一個單獨的進程當中,就可以這樣寫:

    [java]?view plaincopy
  • <service?android:name=".PlaybackService"??
  • ?????????android:process=":background"?/>??
  • 這里指定的進程名是background,你也可以將它改成任意你喜歡的名字。需要注意的是,進程名的前面都應該加上一個冒號,表示該進程是一個當前應用程序的私有進程。

    遵循以上的所有編程建議,我們就可以讓應用程序內存的使用變得更加合理化。但這只是第一步而已,為了要讓程序擁有最佳性能,我們要學習的東西還有很多,下篇文章當中將會介紹如何分析內存的使用情況,感興趣的朋友請繼續閱讀?Android最佳性能實踐(二)——分析內存的使用情況?。

    第一時間獲得博客更新提醒,以及更多技術信息分享,歡迎關注我的微信公眾號,掃一掃下方二維碼或搜索微信號guolin_blog,即可關注。

    總結

    以上是生活随笔為你收集整理的Android最佳性能实践(一)——合理管理内存的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 97性视频| 亚洲免费在线 | 成人四色| 国内激情 | 亚洲精品97久久中文字幕 | 亚洲精品在线视频 | 折磨小男生性器羞耻的故事 | 99久久精品国产毛片 | 成人免费观看网站 | 午夜性福利 | 熟女一区二区三区四区 | 美女黄页网站 | av桃色| 涩涩涩999 | 国产黄色激情视频 | 久操不卡 | 特级a毛片 | 操皮视频 | 日韩有码视频在线 | 欧美成人免费播放 | 亚洲婷婷免费 | 欧美大片在线看免费观看 | 色羞羞 | 亚洲天堂aaa | 国产激情在线观看 | 天天天天天天干 | 精品国产一区二区三区性色av | 亚洲青涩网| 欧美性生交大片免费看 | 国产第四页| 四虎国产精品永久在线国在线 | 欧洲亚洲成人 | 中文黄色片| 久久亚洲精少妇毛片午夜无码 | 国产精品一区二区久久毛片 | 综合天堂av久久久久久久 | 日韩一区二区在线看 | 日韩精品一区二区三区中文字幕 | 国产无码精品久久久 | 午夜伦伦 | 小色瓷导航 | 91成人免费网站 | 久久久久99精品成人片 | 特色特色大片在线 | 深夜成人福利视频 | 日韩精品字幕 | 台湾swag在线观看 | 国产精品视频久久 | av资源共享 | 密桃成熟时在线观看 | 澳门一级黄色片 | 精品妇女一区二区三区 | 人妻体体内射精一区二区 | 女人被狂躁c到高潮喷水电影 | 国产精品v日韩精品v在线观看 | 国产精品亚洲αv天堂无码 伊人性视频 | 狠狠干狠狠插 | 国产一av| 特黄aaaaaaaaa毛片免 | 欧美aⅴ在线观看 | 男女激情久久 | 日韩高清专区 | 国产伦精品一区二区三区免费迷 | 开心激情综合 | 国产成年人视频 | 久久4| 自拍偷拍国产 | 青青草色视频 | 欧美a在线看 | 日本精品网站 | 国产露脸无套对白在线播放 | 老司机精品视频在线 | 亚洲精品久久夜色撩人男男小说 | 国产欧美一区二区精品性色 | 男人的天堂你懂的 | 亚洲成网| 蜜桃视频成人 | 精品久久中文 | 日韩av在线免费播放 | 久国产精品 | 99久久久无码国产精品性青椒 | 欧洲毛片 | 尤物在线 | 日韩高清精品免费观看 | 日本在线国产 | 日韩va亚洲va欧美va久久 | 人妻少妇被猛烈进入中文字幕 | 在线亚洲区 | 中文字幕人成人乱码亚洲电影 | 国产视频在线免费观看 | 国产成人综合在线观看 | 777视频在线观看 | 欧美群妇大交群 | 国产尤物视频在线 | 国产精品sm调教免费专区 | 久久精品国产亚洲av高清色欲 | 亚洲视频 一区 | 少女忠诚电影高清免费 | xxxxx色|