編輯:Android開發教程
做了較長時間的android開發了,發現其實android應用開發入門容易,但是進階或者成為高級工程師,需要具備的基礎能力還是非常高的:性能優化、內存洩露、apk瘦身、熱修復等等,這些都非常的考驗一個人的能力。android成長之路還很長,自己會持續的走下去。本文主要介紹android內存洩露方面的知識。其實要真的理解內存洩露,需要對JVM、java語言有一定的了解,在這個基礎上就比較容易理解本文了。
在java中,如果一個對象沒有可用價值了,但又被其他引用所指向,那麼這個對象對於gc來說就不是一個垃圾, 所以不會對其進行回收,但是我們認為這應該是個垃圾,應該被gc回收的。這個對象得不到gc的回收, 就會一直存活在堆內存中,占用內存,就跟我們說的霸著茅坑不拉屎的道理是一樣的。這樣就導致了內存的洩露。
為什麼會內存洩露呢,根本原因就是一個永遠不會被使用的對象,因為一些引用沒有斷開,沒有滿足GC條件,導致不會被回收,這就造成了內存洩露。比如在Activity中注冊了一個廣播接收器,但是在頁面關閉的時候進行unRegister,就會出現內存溢出的現象。如果我們的java運行很久,而這種內存洩露不斷的發生,最後就沒內存可用了,最終就是我們看到的OOM錯誤。雖然android的內存洩露做到了應用程序級別的洩露(android中的每個應用程序都是獨立運行在單獨進程中的,每個應用進程都由虛擬機指定了一個內存上限值,一旦內存占用值超過這個上限值,就會發生oom錯誤,進程被強制kill掉,kill掉的進程內存會被系統回收),但是對於一名開發工程師,絕對不能放過任何的內存洩露。
{ Handler mLeakyHandler = Handler() { (Message msg) { } } (Bundle savedInstanceState) { .onCreate(savedInstanceState); mLeakyHandler.postDelayed( Runnable() { () { } }, * * ); } }
當這個Activity被finished後,延時發送的消息會繼續在主線程的消息隊列中存活10分鐘,直到他們被處理。這個消息持有這個Activity的Handler引用,這個Handler有隱式地持有他的外部類(在這個例子中是SampleActivity)。直到消息被處理前,這個引用都不會被釋放。因此Activity不會被垃圾回收機制回收,洩露他所持有的應用程序資源。注意,第15行的匿名Runnable類也一樣。匿名類的非靜態實例持有一個隱式的外部類引用,因此context將被洩露。
具體的引用順序:
MessageQueue->Message->Runnable->Handler->Activity。所以這就導致當前activity與MessageQueue一直有關聯,導致LeakActivity的對象不能被gc回收,從而導致內存洩露。
為了解決這個問題,Handler的子類應該定義在一個新文件中或使用靜態內部類。靜態內部類不會隱式持有外部類的引用。所以不會導致它的Activity洩露。如果你需要在Handle內部調用外部Activity的方法,那麼讓Handler持有一個Activity的弱引用(WeakReference)以便你不會意外導致context洩露。為了解決我們實例化匿名Runnable類可能導致的內存洩露,我們將用一個靜態變量來引用他(因為匿名類的靜態實例不會隱式持有他們外部類的引用)。
{ Runnable sRunnable = Runnable() { () { } }; MyHandler mHandler = MyHandler(); (Bundle savedInstanceState) { .onCreate(savedInstanceState); mHandler.postDelayed(sRunnable, * * ); finish(); } { WeakReference<SampleActivity> mActivity; (SampleActivity activity) { mActivity = WeakReference<SampleActivity>(activity); } (Message msg) { SampleActivity activity = mActivity.get(); (activity != ) { } } } }
一、關於AndroidManifest.xmlAndroidManifest.xml 是每個android程序中必須的文件。它位於整 個項目的根目錄,描述了package
上節已經在openfire服務器中建立了組,這節繼續看怎樣獲取好友列表,通過connection對象得到roster,從而可以使用roster.getGroups()得到
筆者有一段時間沒有發表關於Android的文章了,關於Android自定義組件筆者有好幾篇想跟大家分享的,後期會記錄在博客中。本篇博客給大家分享的是自定義一個日期選擇器,
其實我一直准備寫一篇關於Android事件分發機制的文章,從我的第一篇博客開始,就零零散散在好多地 方使用到了Android事件分發的知識。也有好多朋友問過我各種問題,比