編輯:Android編程入門
Android開發經常會用到handler,但是我們發現每次使用Handler都會出現:This Handler class should be static or leaks might occur(null)這樣的提示。Android lint就是為了提示我們,這樣使用Handler會容易造成內存洩漏。但是你會發現其實改成static並沒有什麼用。因為這並沒有解決這個問題的根本。
首先,我們得確認,為什麼會有內存洩漏?因為Handler是基於消息的。每次new 出Handler,都會創建一個消息隊列用於處理你使用handler發送的消息,形如:handler.send***Message。由於消息的發送總是會有先來後到的區別(如果只是這樣都還好,畢竟再慢也不會太久,總歸可以跑完,可能會延遲個幾秒),但是如果你使用的是sendMessageDelayed(Message msg, long delayMillis)或postDelayed(Runnable r, long delayMillis)等發送延遲消息的時候,那基本內存洩漏發生的概率已經在90%以上了。
我舉個通常的例子,就是我們在Activity中使用handler來更新UI控件,這是比較常見的。
public class DemoActivity extends Activity { private Handler mHandler; protected void onCreate(Bundle savedInstanceState) { mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
Log.i("wytings","-----------postDelayed-------"); view.setVisibility(View.GONE); }, 50000);
... }
... }
如果我們瘋狂的對這個Activity進行橫屏和豎屏切換的話,那麼Activity就會不斷的被銷毀和重建。理論上被關閉的Activity應該會再特定時候被回收,也就是我們的內存會在一定的范圍內上下起伏,但是實際上,會發現消耗的內存會隨著切換橫屏的次數一直慢慢增加。這其實已經說明我們的內存洩漏了,如果你會查看內存,你會發現裡面有成堆的DemoActivity實例沒辦法回收。
這是因為view中使用的Context就是當前的Activity,而這個runnable一旦被post,就會一直存在於隊列裡面,直到時間到了,被執行。意思是這個時間段內Activity即使已經被destroy了但是這個對象還是沒辦法回收,你會發現50秒好,會有一堆"-----------postDelayed-------"的log打印出來,雖然你已經被這個應用關閉了並且你以為即使打印也應該只打印一次……
那怎麼樣才可以避免這中問題呢,如果你網上一搜你會看到很多關於弱引用的文章。這確實是一個解決的辦法。其原理就是讓所有在handler裡面使用的對象都變成弱引用,目的就是為了可以在Android回收內存的時候,可以直接回收掉。我真覺得如果只是寫這種辦法的人,絕對是屬於拷貝黨,因為這完全是就事論事。你想想就明白,我們寫這個Handler是因為我們要使用它。怎麼可以通過這種弱引用的辦法去處理這類問題呢?讓JVM想回收就回收?!如果這樣,那我們還需要在使用Bitmap的時候,recycle()干嘛,還不如直接弄成軟引用得了。
這裡需要再插播一下關於Java裡面引用的知識:
如果你運氣好,你會碰到一些除了寫弱引用這個方法後,還有一個就是handler.removeCallbacksAndMessages(null);,就是移除所有的消息和回調,簡單一句話就是清空了消息隊列。注意,不要以為你post的是個Runnable或者只是sendEmptyMessage。你可以看一下源碼,在handler裡面都是會把這些轉成正統的Message,放入消息隊列裡面,所以清空隊列就意味著這個Handler直接被打成原型了,當然也就可以回收了。
所以,我覺得最好的辦法就是你在使用Handler的時候,在外面的Activity或者Fragment中的關閉方法中,如onDestroy中調用一下handler.removeCallbacksAndMessages(null);就可以了,不應該改成軟引用。
PS:還有幾天就開學了.先來一發. 學習內容:1.序列化的目的2.Android中序列化的兩種方式3.Parcelable與Serializable的性能比較4
項目裡要用到開獎公告,單行顯示向上滾動的TextView,網上隨便找了一個控件發現效果還不錯改裝一下就可以用到項目裡。唯一不妥的地方就是字體大小不太好控制,不是正常的字體
前面幾節,我們重點討論了自定義View的三板斧,這節我們來討論自定義ViewGroup,為什麼要自定義ViewGroup,其實就是為了更好的管理View。 自定義Vie
1.5版本的android studio上傳本地項目到git@osc上:1、在git上創建一個項目;2、在studio上導入git上新創建的項目:把git上的地址復制下來