內(nèi)存不夠用?講講Android開(kāi)發(fā)超常見(jiàn)的內(nèi)存泄露以及解決
有沒(méi)有感覺(jué)自己的Android手機(jī)開(kāi)機(jī)之后,可用內(nèi)存不斷減少,很大一部分原因就是因?yàn)閮?nèi)存泄露了,這部分泄露的內(nèi)存無(wú)法被回收,所以可用內(nèi)存越來(lái)越少;
什么是內(nèi)存泄露?GC無(wú)法回收原本應(yīng)該被回收的對(duì)象,這個(gè)對(duì)象就引發(fā)了內(nèi)存泄露
1.Bitmap使用完忘記回收,因?yàn)閎itmap實(shí)現(xiàn)部分是通過(guò)JNI調(diào)用了Native方法,GC機(jī)制無(wú)法正常回收 Bitmap申請(qǐng)的這部分內(nèi)存空間(API10之前是這樣的,之后分配在Heap中,不過(guò)為了兼容老版本...顯示的調(diào)用一下recycled,也能讓GC更快的回收調(diào)自己);
那Bitmap應(yīng)該怎樣回收呢?
- // bitmap!=null要放在前面,如果bitmap為空再去調(diào)用isRecycled方法便會(huì)報(bào)錯(cuò)
- if(bitmap!=null&&!bitmap.isRecycled){
- bitmap.recycled(); //回收bitmap
- bitmap = null; //使bitmap對(duì)象變?yōu)樘撘玫臓顟B(tài),讓GC更快的回收
- }
接下來(lái),講兩個(gè)更為常見(jiàn)的內(nèi)存泄露,大家根據(jù)這兩個(gè)可以自行擴(kuò)展
- btn_hint.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
- }
- });
是不是很常見(jiàn),平時(shí)可能也是這樣寫(xiě)的(將其封裝意義一樣,只要引用了當(dāng)前activity),你可能想問(wèn),這里有什么問(wèn)題嗎?
問(wèn)題在于如果用戶(hù)在Toast消失之前,用戶(hù)按了返回鍵,這個(gè)Activity就引起了內(nèi)存泄露,
原因? Toast持有了當(dāng)前Activity,導(dǎo)致Activity無(wú)法被GC銷(xiāo)毀
解決方法:讓Toast持有ApplicationContext;其實(shí)只要不是Layout,Context都可以使用ApplicationContext;
順便講個(gè)小技巧:在非Activity中,正常是不能直接getContext來(lái)拿到Context的,獲取資源有需要靠Context,這時(shí)可以考慮在自己的Application中維護(hù)一個(gè)全局的Context,供無(wú)法直接拿到Context的類(lèi)使用,省的參數(shù)傳來(lái)傳去(視圖相關(guān)的不建議使用ApplicationContext)
- private static Context mContext;
- public static MyApplication getInstance() { //供外界調(diào)用...
- return mApplication;
- }
- @Override
- public void onCreate() {
- super.onCreate();
- mContext = getApplicationContext();
- }
另一個(gè)常見(jiàn)的...內(nèi)存泄露
- new Thread() {
- public void run() {
- //網(wǎng)絡(luò)請(qǐng)求
- };
- }.start();
這里也有問(wèn)題?你tm逗我?
在Activity中 新建一個(gè)線(xiàn)程,進(jìn)行網(wǎng)絡(luò)請(qǐng)求,如果線(xiàn)程未結(jié)束,用戶(hù)按了返回鍵,同樣內(nèi)存泄露
原因:該Thread是匿名內(nèi)部類(lèi),所以會(huì)隱式的持有外部類(lèi)(這里也就是Activity)
解決方式:多種多樣; 不使用匿名內(nèi)部類(lèi),或者整個(gè)應(yīng)用維護(hù)一個(gè)線(xiàn)程池,或者維護(hù)一個(gè)線(xiàn)程隊(duì)列,后兩種都是讓線(xiàn)程不依賴(lài)于Activity從而達(dá)到避免內(nèi)存泄露的目的;
資源獲取等等很多地方都需要用到Context,很多地方都會(huì)用到匿名內(nèi)部類(lèi),這也就導(dǎo)致了這里存在很大的內(nèi)存泄露隱患,但平時(shí)很多小伙伴可能還沒(méi)有注意到,希望這篇文章能給你一些啟發(fā)。