国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

內存泄漏的檢測、幾種常見場景及解決方法

2019-11-06 09:36:59
字體:
來源:轉載
供稿:網友

文章參考:http://blog.nimbledroid.com/2016/05/23/memory-leaks.html

使用AndroidStudio檢測內存泄漏:

http://wetest.QQ.com/lab/view/99.html

一.內存泄漏的原因

一般內存泄漏(traditional memory leak)的原因是:由忘記釋放分配的內存導致的。邏輯內存泄漏(logical memory leak)的原因是:當應用不再需要這個對象,當仍未釋放該對象的所有引用。

二.幾種常見的內存泄漏場景

實例代碼一: MainActivity:

public class MainActivity extends AppCompatActivity { TextView tv_test; PRivate Handler handler = new MyHandler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_test = (TextView) findViewById(R.id.tv_test); Message message = Message.obtain(); message.what = 0; message.obj = "000"; handler.sendMessageDelayed(message,60000); new Util(this,handler); } @Override protected void onDestroy() { super.onDestroy(); //handler.removeCallbacksAndMessages(null); } class MyHandler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); tv_test.setText((CharSequence) msg.obj); } }}

Util代碼:

public class Util { private static Context context; private static Handler handler; Util(Context context,Handler handler){ this.context = context; this.handler = handler; }}

場景一:靜態變量持有了Activity

由于Util中的context是static的,即其生命周期是和應用一樣長的,在MainActivity方法中創建Util對象的時候,持有了MainActivity的引用(即this),導致該MainActivity無法被垃圾回收器回收,這樣就造成了內存泄漏。

場景二:匿名內部類或非靜態內部類引起的內存泄漏

內部類會隱式地持有了外部類。在該例子中,MyHandler會持有MainActivity的引用,而Util中的靜態變量又持有了MyHandler的引用,這樣還是靜態變量間接地持有了Activity,導致Activity無法被垃圾回收器回收。 另外還有其它幾種常見的實例 實例一:TimerTask

private void scheduleTimer() { new Timer().schedule(new TimerTask() { @Override public void run() { while(true); } }, Long.MAX_VALUE >> 1); }實例二:void spawnThread() { new Thread() { @Override public void run() { while(true); } }.start(); }

該方法若在Activity中,由于TimerTask使用的是匿名內部類,會持有Activity的引用,因此會造成內存泄漏。其實這個是匿名內部類導致內存泄漏的一個實例。

場景三:Handler

因為Handler是基于消息的。每次new出Handler,都會創建一個消息隊列用于處理你使用handler發送的消息,形如:handler.send***Message。由于消息的發送總是會有先來后到的區別(如果只是這樣都還好,畢竟再慢也不會太久,總歸可以跑完,可能會延遲個幾秒),但是如果你使用的是sendMessageDelayed(Message msg, long delayMillis)或postDelayed(Runnable r, long delayMillis)等發送延遲消息的時候,那基本內存泄漏發生的概率已經在90%以上了。因為handler會持有MainActivity的引用,會導致MainActivity無法銷毀。   

場景四:Static Views

private static View view;void setStaticView() { view = findViewById(R.id.sv_button);}

由于View持有其宿主Activity的引用,故和原因一其實是一樣的。

場景五:無限循環的屬性動畫

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv_test,"rotation",0,360).setDuration(2000); objectAnimator.setRepeatCount(ValueAnimator.INFINITE); objectAnimator.start();

若在OnDestory()中沒有停止動畫,則動畫即時不可見,仍會一直執行下去,tv_test持有Activity的引用,故會導致Activity無法被回收

三.解決方案

針對場景一: 靜態變量不要持有Activity,若無特殊需求,將其改為一般的變量針對原因二: 將非靜態內部類/匿名內部類替換為靜態內部類,這樣就不會持有外部類的引用了針對場景三: 在onDestory()中調用handler.removeCallbacksAndMessages(null);,就是移除所有的消息和回調,簡單一句話就是清空了消息隊列。注意,不要以為你post的是個Runnable或者只是sendEmptyMessage。你可以看一下源碼,在handler里面都是會把這些轉成正統的Message,放入消息隊列里面,所以清空隊列就意味著這個Handler直接被打成原型了,當然也就可以回收了。針對場景四: 盡量不要用靜態的view,若必須使用,需在onDestory的時候將view置為null針對場景五: 在onDestory()中,停止動畫 objectAnimator.cancel();

四.總結:

定義變量的時候,慎用static,例如若使用靜態的集合,集合中的數據都不會被回收及時回收需要回收的資源,如bitmap,cursor等使用非靜態內部類或匿名內部類的時候要注意

如有問題,歡迎加群交流:579853893


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 民乐县| 托克逊县| 五原县| 廊坊市| 岑巩县| 鞍山市| 公主岭市| 嵊泗县| 桃园县| 论坛| 鲁山县| 通化市| 晴隆县| 湟中县| 徐闻县| 商洛市| 庄河市| 阆中市| 汤阴县| 孝昌县| 沙田区| 丹江口市| 嘉祥县| 彰化市| 英山县| 都江堰市| 贡山| 忻城县| 长武县| 兴宁市| 蓬安县| 怀仁县| 石阡县| 晴隆县| 西宁市| 吉木乃县| 宣城市| 金溪县| 吉木萨尔县| 独山县| 浑源县|