Android編碼的常見錯誤及解決方法分享
在android編碼中,會有一些簡便的寫法和編碼習慣,會導致我們的代碼有很多內存泄露的問題,在這裏做一個已知錯誤的總結:
1、編寫單例的時候常出現的錯誤。
錯誤方式:
public class Foo{ private static Foo foo; private Context mContext; private Foo(Context mContext){ text = mContext; } // 普通單例,非線程安全 public static Foo getInstance(Context mContext){ if(foo == null) foo = new Foo(mContext); return foo; } public void otherAction(){ (); …. } }
錯誤原因:
如果我們在Activity A中或者其他地方使用nstance()時,我們總是會順手寫一個『this』或者『mContext』(這個變量也是指向this)。試想一下,當前我們所用的Foo是單例,意味着被初始化後會一直存在與內存中,以方便我們以後調用的時候不會在此次創建Foo對象。但Foo中的『mContext』變量一直都會持有Activity A中的『Context』,導致Activity A即使執行了onDestroy方法,也不能夠將自己銷燬。但『applicationContext』就不同了,它一直伴隨着我們應用存在(中途也可能會被銷燬,但也會自動reCreate),所以就不用擔心Foo中的『mContext』會持有某Activity的引用,讓其無法銷燬。
正確方式:
public class Foo{ private static Foo foo; private Context mContext; private Foo(Context mContext){ text = mContext; } // 普通單例,非線程安全 public static Foo getInstance(Context mContext){ if(foo == null) foo = new Foo(pplicationContext()); return foo; } public void otherAction(){ (); …. } }
2、使用匿名內部類的時候經常出現的錯誤
錯誤方式:
public class FooActivity extends Activity{ private TextView textView; private Handler handler = new Handler(){ @override public void handlerMessage(Message msg){ } }; @override public void onCreate(Bundle bundle){ eate(bundle); setContextView(vity_foo_layout); textView = (TextView)findViewById(View); Delayed(new Runnable(){ @override public void run(){ ext(“ok”); }; },1000 * 60 * 10); } }
錯誤原因:
當我們執行了FooActivity的finish方法,被延遲的消息會在被處理之前存在於主線程消息隊列中10分鐘,而這個消息中又包含了Handler的引用,而Handler是一個匿名內部類的實例,其持有外面的FooActivity的'引用,所以這導致了FooActivity無法回收,進而導致FooActivity持有的很多資源都無法回收,所以產生了內存泄露。
注意上面的new Runnable這裏也是匿名內部類實現的,同樣也會持有FooActivity的引用,也會阻止FooActivity被回收。
一個靜態的匿名內部類實例不會持有外部類的引用。
正確方式:
public class FooActivity extends Activity{ private TextView textView; private static class MyHandler extends Handler { private final WeakReference
3、在使用handler後,記得在onDestroy裏面veCallbacksAndMessages(object token);
veCallbacksAndMessages(null); // removeCallbacksAndMessages,當參數為null的時候,可以清除掉所有跟次handler相關的Runnable和Message,我們在onDestroy中調用次方法也就不會發生內存泄漏了。
開發中需要注意的點以免內存泄漏:
1.不要讓生命週期長於Activity的對象持有到Activity的引用 2.儘量使用Application的Context而不是Activity的Context 3.儘量不要在Activity中使用非靜態內部類,因為非靜態內部類會隱式持有外部類實例的引用(具體可以查看細話Java:”失效”的private修飾符瞭解)。如果使用靜態內部類,將外部實例引用作為弱引用持有。 4.垃圾回收不能解決內存泄露,瞭解Android中垃圾回收機制
獲取context的方法,以及使用上context和applicationContext的區別:
ontext,返回當前View對象的Context對象,通常是當前正在展示的Activity對象。 pplicationContext,獲取當前Activity所在的(應用)進程的Context對象,通常我們使用Context對象時,要優先考慮這個全局的進程Context。 3,aseContext():用來獲取一個ContextWrapper進行裝飾之前的Context,可以使用這個方法,這個方法在實際開發中使用並不多,也不建議使用。 返回當前的Activity實例,如果是UI控件需要使用Activity作為Context對象,但是默認的Toast實際上使用ApplicationContext也可以。
大家注意看到有一些NO上添加了一些數字,其實這些從能力上來説是YES,但是為什麼説是NO呢?下面一個一個解釋:
數字1:啟動Activity在這些類中是可以的,但是需要創建一個新的task。一般情況不推薦。
數字2:在這些類中去layout inflate是合法的,但是會使用系統默認的主題樣式,如果你自定義了某些樣式可能不會被使用。
數字3:在receiver為null時允許,在4.2或以上的版本中,用於獲取黏性廣播的當前值。(可以無視)
注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因為在其內部方法中都有一個context用於使用。
好了,這裏我們看下錶格,重點看Activity和Application,可以看到,和UI相關的方法基本都不建議或者不可使用Application,並且,前三個操作基本不可能在Application中出現。實際上,只要把握住一點,凡是跟UI相關的,都應該使用Activity做為Context來處理;其他的一些操作,Service,Activity,Application等實例都可以,當然了,注意Context引用的持有,防止內存泄漏。
-
交通安全班會活動方案
為了確保事情或工作有序有力開展,就常常需要事先準備方案,方案是解決一個問題或者一項工程,一個課題的詳細過程。優秀的方案都具備一些什麼特點呢?下面是小編幫大家整理的交通安全班會活動方案,歡迎閲讀與收藏。交通安全班會活動方案1一、班會目的1、通過班會使學生...
-
理財方案模板彙編六篇
為保障事情或工作順利開展,就常常需要事先準備方案,方案是計劃中內容最為複雜的一種。那麼什麼樣的方案才是好的呢?下面是小編整理的理財方案6篇,僅供參考,歡迎大家閲讀。理財方案篇1一、家庭很富裕李女士29歲,在職研究生,與朋友合夥開了一家公司,每月可分紅3、4萬元,但...
-
大班環保主題活動方案
為了確保工作或事情有序地進行,時常需要預先制定一份周密的方案,方案是解決一個問題或者一項工程,一個課題的詳細過程。優秀的方案都具備一些什麼特點呢?下面是小編整理的大班環保主題活動方案,僅供參考,歡迎大家閲讀。大班環保主題活動方案1活動目標:1知道哪些是危險...
-
實用的評選方案模板五篇
為了確保事情或工作紮實開展,常常需要預先準備方案,方案是書面計劃,是具體行動實施辦法細則,步驟等。那要怎麼制定科學的方案呢?下面是小編整理的評選方案5篇,歡迎大家分享。評選方案篇1一、評選目的:為了進一步加強教研組在學校教育教學和教研工作中的主導作用,充分發...
相關文章
- Win10系統提示Officebackgroundtaskhandler.exe彈窗問題的解決方
- Android內存泄漏終極解決方法介紹
- android5.0系統奔潰解決方法彙總
- 關於Android中EditText光標在4.0中的bug及解決方法
- win8系統Err-Failed錯誤解決方法
- 解決PHP中的Cannot modify header information 問題
- Windows10 彈出defender的解決方法
- 解決PHP的failed opening required問題的方法
- Thinkpad筆記本開機顯示Tointerrruptnormalstartup解決方法
- Windows系統常見的幾個故障及解決方法