摘要:內(nèi)存泄漏會(huì)造成什么影響它是造成應(yīng)用程序的主要原因之一。靜態(tài)變量引用不當(dāng)會(huì)導(dǎo)致內(nèi)存泄漏靜態(tài)變量和會(huì)導(dǎo)致內(nèi)存泄漏,在下面這段代碼中對(duì)的和設(shè)置為靜態(tài)對(duì)象,從而產(chǎn)生內(nèi)存泄漏。
目錄介紹:
1.什么是內(nèi)存泄漏
2.內(nèi)存泄漏造成什么影響
3.內(nèi)存泄漏檢測(cè)的工具有哪些
4.關(guān)于Leakcanary使用介紹
5.Leakcanary捕捉常見的內(nèi)存泄漏及解決辦法
5.0.1 錯(cuò)誤使用單例造成的內(nèi)存泄漏
5.0.2 錯(cuò)誤使用靜態(tài)變量,導(dǎo)致引用后無法銷毀
5.0.3 [常見]Handler使用不當(dāng)造成的內(nèi)存泄漏
5.0.4 線程造成的內(nèi)存泄漏[比較少見]
5.0.5 非靜態(tài)內(nèi)部類創(chuàng)建靜態(tài)實(shí)例造成的內(nèi)存泄漏
5.0.6 不需要用的監(jiān)聽未移除會(huì)發(fā)生內(nèi)存泄露
5.0.7 [常見]資源未關(guān)閉造成的內(nèi)存泄漏
5.0.8 未注銷EventBus導(dǎo)致的內(nèi)存泄漏
5.0.9 [常見]持有activity引用未被釋放導(dǎo)致內(nèi)存泄漏
5.1.0 靜態(tài)集合使用不當(dāng)導(dǎo)致的內(nèi)存泄漏
5.1.1 動(dòng)畫資源未釋放導(dǎo)致內(nèi)存泄漏
5.1.2 系統(tǒng)bug之InputMethodManager導(dǎo)致內(nèi)存泄漏
6.其他建議
6.0.1 盡量避免使用 static 成員變量
7.版本更新
v1.0.0 更新于2016年3月19日
v1.1.0 更新于2017年7月8日
v1.2.0 更新于2018年5月3日
v1.3.0 更新于2018年9月18日
1.什么是內(nèi)存泄漏?一些對(duì)象有著有限的聲明周期,當(dāng)這些對(duì)象所要做的事情完成了,我們希望它們會(huì)被垃圾回收器回收掉。但是如果有一系列對(duì)這個(gè)對(duì)象的引用存在,那么在我們期待這個(gè)對(duì)象生命周期結(jié)束時(shí)被垃圾回收器回收的時(shí)候,它是不會(huì)被回收的。它還會(huì)占用內(nèi)存,這就造成了內(nèi)存泄露。持續(xù)累加,內(nèi)存很快被耗盡。
比如:當(dāng)Activity的onDestroy()方法被調(diào)用后,Activity以及它涉及到的View和相關(guān)的Bitmap都應(yīng)該被回收掉。但是,如果有一個(gè)后臺(tái)線程持有這個(gè)Activity的引用,那么該Activity所占用的內(nèi)存就不能被回收,這最終將會(huì)導(dǎo)致內(nèi)存耗盡引發(fā)OOM而讓應(yīng)用crash掉。
2.內(nèi)存泄漏會(huì)造成什么影響?它是造成應(yīng)用程序OOM的主要原因之一。由于android系統(tǒng)為每個(gè)應(yīng)用程序分配的內(nèi)存有限,當(dāng)一個(gè)應(yīng)用中產(chǎn)生的內(nèi)存泄漏比較多時(shí),就難免會(huì)導(dǎo)致應(yīng)用所需要的內(nèi)存超過這個(gè)系統(tǒng)分配的內(nèi)存限額,這就
3.內(nèi)存泄漏檢測(cè)的工具有哪些最常見的是:Leakcanary
4.關(guān)于Leakcanary使用介紹leakCanary是Square開源框架,是一個(gè)Android和Java的內(nèi)存泄露檢測(cè)庫,如果檢測(cè)到某個(gè) activity 有內(nèi)存泄露,LeakCanary 就是自動(dòng)地顯示一個(gè)通知,所以可以把它理解為傻瓜式的內(nèi)存泄露檢測(cè)工具。通過它可以大幅度減少開發(fā)中遇到的oom問題,大大提高APP的質(zhì)量。
關(guān)于如何配置,這個(gè)就不說呢,網(wǎng)上有步驟
5.Leakcanary捕捉常見的內(nèi)存泄漏及解決辦法 5.0.1 錯(cuò)誤使用單例造成的內(nèi)存泄漏在平時(shí)開發(fā)中單例設(shè)計(jì)模式是我們經(jīng)常使用的一種設(shè)計(jì)模式,而在開發(fā)中單例經(jīng)常需要持有Context對(duì)象,如果持有的Context對(duì)象生命周期與單例生命周期更短時(shí),或?qū)е翪ontext無法被釋放回收,則有可能造成內(nèi)存泄漏,錯(cuò)誤寫法如下:
問題引起內(nèi)存泄漏代碼
public class LoginManager { private static LoginManager mInstance; private Context mContext; private LoginManager(Context context) { this.mContext = context; //修改代碼:this.mContext = context.getApplicationContext(); } public static LoginManager getInstance(Context context) { if (mInstance == null) { synchronized (LoginManager.class) { if (mInstance == null) { mInstance = new LoginManager(context); } } } return mInstance; } public void dealData() {} }
使用場(chǎng)景
在一個(gè)Activity中調(diào)用的,然后關(guān)閉該Activity則會(huì)出現(xiàn)內(nèi)存泄漏。
LoginManager.getInstance(this).dealData();
看看報(bào)錯(cuò)截圖
解決辦法:
要保證Context和AppLication的生命周期一樣,修改后代碼如下:
this.mContext = context.getApplicationContext();
1、如果此時(shí)傳入的是 Application 的 Context,因?yàn)?Application 的生命周期就是整個(gè)應(yīng)用的生命周期,所以這將沒有任何問題。
2、如果此時(shí)傳入的是 Activity 的 Context,當(dāng)這個(gè) Context 所對(duì)應(yīng)的 Activity 退出時(shí),由于該 Context 的引用被單例對(duì)象所持有,其生命周期等于整個(gè)應(yīng)用程序的生命周期,所以當(dāng)前 Activity 退出時(shí)它的內(nèi)存并不會(huì)被回收,這就造成泄漏了。
5.0.2 錯(cuò)誤使用靜態(tài)變量,導(dǎo)致引用后無法銷毀在平時(shí)開發(fā)中,有時(shí)候我們創(chuàng)建了一個(gè)工具類。比如分享工具類,十分方便多處調(diào)用,因此使用靜態(tài)方法是十分方便的。但是創(chuàng)建的對(duì)象,建議不要全局化,全局化的變量必須加上static。這樣會(huì)引起內(nèi)存泄漏!
問題代碼
使用場(chǎng)景
在Activity中引用后,關(guān)閉該Activity會(huì)導(dǎo)致內(nèi)存泄漏
DoShareUtil.showFullScreenShareView(PNewsContentActivity.this, title, title, shareurl, logo);
查看報(bào)錯(cuò)
解決辦法
靜態(tài)方法中,創(chuàng)建對(duì)象或變量,不要全局化,全局化后的變量或者對(duì)象會(huì)導(dǎo)致內(nèi)存泄漏;popMenuView和popMenu都不要全局化
知識(shí)延伸
非靜態(tài)內(nèi)部類,靜態(tài)實(shí)例化 public class MyActivity extends AppCompatActivity { //靜態(tài)成員變量 public static InnerClass innerClass = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); innerClass = new InnerClass(); } class InnerClass { public void doSomeThing() {} } } 這里內(nèi)部類InnerClass隱式的持有外部類MyActivity的引用,而在MyActivity的onCreate方法中調(diào)用了。 這樣innerClass就會(huì)在MyActivity創(chuàng)建的時(shí)候是有了他的引用,而innerClass是靜態(tài)類型的不會(huì)被垃圾回收, MyActivity在執(zhí)行onDestory方法的時(shí)候由于被innerClass持有了引用而無法被回收,所以這樣MyActivity就總是被innerClass持有而無法回收造成內(nèi)存泄露。 靜態(tài)變量引用不當(dāng)會(huì)導(dǎo)致內(nèi)存泄漏 靜態(tài)變量Activity和View會(huì)導(dǎo)致內(nèi)存泄漏,在下面這段代碼中對(duì)Activity的Context和TextView設(shè)置為靜態(tài)對(duì)象,從而產(chǎn)生內(nèi)存泄漏。 public class MainActivity extends AppCompatActivity { private static Context context; private static TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; textView = new TextView(this); } }5.0.3 Handler使用不當(dāng)造成的內(nèi)存泄漏
handler是工作線程與UI線程之間通訊的橋梁,只是現(xiàn)在大量開源框架對(duì)其進(jìn)行了封裝,我們這里模擬一種常見使用方式來模擬內(nèi)存泄漏情形。
問題代碼
public class MainActivity extends AppCompatActivity { private Handler mHandler = new Handler(); private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.text); //模擬內(nèi)存泄露 mHandler.postDelayed(new Runnable() { @Override public void run() { mTextView.setText("yangchong"); } }, 2000); } }
造成內(nèi)存泄漏原因分析
上述代碼通過內(nèi)部類的方式創(chuàng)建mHandler對(duì)象,此時(shí)mHandler會(huì)隱式地持有一個(gè)外部類對(duì)象引用這里就是MainActivity,當(dāng)執(zhí)行postDelayed方法時(shí),該方法會(huì)將你的Handler裝入一個(gè)Message,并把這條Message推到MessageQueue中,MessageQueue是在一個(gè)Looper線程中不斷輪詢處理消息,那么當(dāng)這個(gè)Activity退出時(shí)消息隊(duì)列中還有未處理的消息或者正在處理消息,而消息隊(duì)列中的Message持有mHandler實(shí)例的引用,mHandler又持有Activity的引用,所以導(dǎo)致該Activity的內(nèi)存資源無法及時(shí)回收,引發(fā)內(nèi)存泄漏。
查看報(bào)錯(cuò)結(jié)果如下:
解決方案
第一種解決辦法
要想避免Handler引起內(nèi)存泄漏問題,需要我們?cè)贏ctivity關(guān)閉退出的時(shí)候的移除消息隊(duì)列中所有消息和所有的Runnable。
上述代碼只需在onDestroy()函數(shù)中調(diào)用mHandler.removeCallbacksAndMessages(null);就行了。
@Override protected void onDestroy() { super.onDestroy(); if(handler!=null){ handler.removeCallbacksAndMessages(null); handler = null; } }
* 第二種解決方案 - 使用弱引用解決handler內(nèi)存泄漏問題 ``` public class SampleActivity extends Activity { private static class MyHandler extends Handler { private final WeakReference5.0.4 線程造成的內(nèi)存泄漏mActivity; public MyHandler(SampleActivity activity) { mActivity = new WeakReference (activity); } @Override public void handleMessage(Message msg) { SampleActivity activity = mActivity.get(); if (activity != null) { // ... } } private final MyHandler mHandler = new MyHandler(this); private static final Runnable sRunnable = new Runnable() { @Override public void run() { /* ... */ } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler.postDelayed(sRunnable, 1000 * 60 * 10); finish(); } } 即推薦使用靜態(tài)內(nèi)部類 + WeakReference 這種方式。每次使用前注意判空。 ```
早時(shí)期的時(shí)候處理耗時(shí)操作多數(shù)都是采用Thread+Handler的方式,后來逐步被AsyncTask取代,直到現(xiàn)在采用RxJava的方式來處理異步。這里以AsyncTask為例,可能大部分人都會(huì)這樣處理一個(gè)耗時(shí)操作然后通知UI更新結(jié)果:
問題代碼
public class MainActivity extends AppCompatActivity { private AsyncTaskasyncTask; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.text); testAsyncTask(); finish(); } private void testAsyncTask() { asyncTask = new AsyncTask () { @Override protected Integer doInBackground(Void... params) { int i = 0; //模擬耗時(shí)操作 while (!isCancelled()) { i++; if (i > 1000000000) { break; } Log.e("LeakCanary", "asyncTask---->" + i); } return i; } @Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); mTextView.setText(String.valueOf(integer)); } }; asyncTask.execute(); } }
造成內(nèi)存泄漏原因分析
在處理一個(gè)比較耗時(shí)的操作時(shí),可能還沒處理結(jié)束MainActivity就執(zhí)行了退出操作,但是此時(shí)AsyncTask依然持有對(duì)MainActivity的引用就會(huì)導(dǎo)致MainActivity無法釋放回收引發(fā)內(nèi)存泄漏
查看報(bào)錯(cuò)結(jié)果如下:
解決辦法
在使用AsyncTask時(shí),在Activity銷毀時(shí)候也應(yīng)該取消相應(yīng)的任務(wù)AsyncTask.cancel()方法,避免任務(wù)在后臺(tái)執(zhí)行浪費(fèi)資源,進(jìn)而避免內(nèi)存泄漏的發(fā)生
private void destroyAsyncTask() { if (asyncTask != null && !asyncTask.isCancelled()) { asyncTask.cancel(true); } asyncTask = null; } @Override protected void onDestroy() { super.onDestroy(); destroyAsyncTask(); }5.0.5 非靜態(tài)內(nèi)部類創(chuàng)建靜態(tài)實(shí)例造成的內(nèi)存泄漏
有的時(shí)候我們可能會(huì)在啟動(dòng)頻繁的Activity中,為了避免重復(fù)創(chuàng)建相同的數(shù)據(jù)資源,可能會(huì)出現(xiàn)這種寫法
問題代碼
private static TestResource mResource = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(mResource == null){ mResource = new TestResource(); } } class TestResource { //里面代碼引用上下文,Activity.this會(huì)導(dǎo)致內(nèi)存泄漏 }
解決辦法
將該內(nèi)部類設(shè)為靜態(tài)內(nèi)部類或?qū)⒃搩?nèi)部類抽取出來封裝成一個(gè)單例,如果需要使用Context,請(qǐng)按照上面推薦的使用Application 的 Context。
分析問題
這樣就在Activity內(nèi)部創(chuàng)建了一個(gè)非靜態(tài)內(nèi)部類的單例,每次啟動(dòng)Activity時(shí)都會(huì)使用該單例的數(shù)據(jù),這樣雖然避免了資源的重復(fù)創(chuàng)建,不過這種寫法卻會(huì)造成內(nèi)存泄漏,因?yàn)榉庆o態(tài)內(nèi)部類默認(rèn)會(huì)持有外部類的引用,而該非靜態(tài)內(nèi)部類又創(chuàng)建了一個(gè)靜態(tài)的實(shí)例,該實(shí)例的生命周期和應(yīng)用的一樣長(zhǎng),這就導(dǎo)致了該靜態(tài)實(shí)例一直會(huì)持有該Activity的引用,導(dǎo)致Activity的內(nèi)存資源不能正?;厥?。
5.0.6 不需要用的監(jiān)聽未移除會(huì)發(fā)生內(nèi)存泄露
問題代碼
//add監(jiān)聽,放到集合里面 tv.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() { @Override public void onWindowFocusChanged(boolean b) { //監(jiān)聽view的加載,view加載出來的時(shí)候,計(jì)算他的寬高等。 } });
解決辦法
//計(jì)算完后,一定要移除這個(gè)監(jiān)聽 tv.getViewTreeObserver().removeOnWindowFocusChangeListener(this);
注意事項(xiàng):
tv.setOnClickListener();//監(jiān)聽執(zhí)行完回收對(duì)象,不用考慮內(nèi)存泄漏 tv.getViewTreeObserver().addOnWindowFocusChangeListene,add監(jiān)聽,放到集合里面,需要考慮內(nèi)存泄漏5.0.7 [常見]資源未關(guān)閉造成的內(nèi)存泄漏
BroadcastReceiver,ContentObserver,F(xiàn)ileObserver,Cursor,Callback等在 Activity onDestroy 或者某類生命周期結(jié)束之后一定要 unregister 或者 close 掉,否則這個(gè) Activity 類會(huì)被 system 強(qiáng)引用,不會(huì)被內(nèi)存回收。值得注意的是,關(guān)閉的語句必須在finally中進(jìn)行關(guān)閉,否則有可能因?yàn)楫惓N搓P(guān)閉資源,致使activity泄漏。
- 比如我們?cè)贏ctivity中注冊(cè)廣播,如果在Activity銷毀后不取消注冊(cè),那么這個(gè)廣播會(huì)一直存在系統(tǒng)中,同上面所說的非靜態(tài)內(nèi)部類一樣持有Activity引用,導(dǎo)致內(nèi)存泄露。因此注冊(cè)廣播后在Activity銷毀后一定要取消注冊(cè)。 - 在注冊(cè)觀察則模式的時(shí)候,如果不及時(shí)取消也會(huì)造成內(nèi)存泄露。比如使用Retrofit+RxJava注冊(cè)網(wǎng)絡(luò)請(qǐng)求的觀察者回調(diào),同樣作為匿名內(nèi)部類持有外部引用,所以需要記得在不用或者銷毀的時(shí)候取消注冊(cè)。 ``` public class MeAboutActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.registerReceiver(mReceiver, new IntentFilter()); } private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 接收到廣播需要做的邏輯 } }; @Override protected void onDestroy() { super.onDestroy(); this.unregisterReceiver(mReceiver); } } ```
在使用IO、File流或者Sqlite、Cursor等資源時(shí)要及時(shí)關(guān)閉。這些資源在進(jìn)行讀寫操作時(shí)通常都使用了緩沖,如果及時(shí)不關(guān)閉,這些緩沖對(duì)象就會(huì)一直被占用而得不到釋放,以致發(fā)生內(nèi)存泄露。因此我們?cè)诓恍枰褂盟鼈兊臅r(shí)候就及時(shí)關(guān)閉,以便緩沖能及時(shí)得到釋放,從而避免內(nèi)存泄露。
5.0.8 未注銷EventBus導(dǎo)致的內(nèi)存泄漏
直接展示代碼
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_common); EventBus.getDefault().register(this); } @Subscribe public void onEvent(MessageEvent msg) { } @Override protected void onDestroy() { super.onDestroy(); //未移除注冊(cè)的EventBus //EventBus.getDefault().unregister(this); }5.0.9 持有activity引用未被釋放導(dǎo)致內(nèi)存泄漏
先看看問題代碼
這個(gè)是在開發(fā)中經(jīng)常會(huì)犯的錯(cuò)誤,NastyManager.getInstance() 是一個(gè)單例,當(dāng)我們通過 addListener(this) 將 Activity 作為 Listener 和 NastyManager 綁定起來的時(shí)候,由于單例和Activity生命周期不同,因此銷毀時(shí)就會(huì)導(dǎo)致內(nèi)存泄漏。
public class LeakActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NastyManager.getInstance().addListener(this); } }
解決辦法:
在你的 Acitivity 被銷毀的時(shí)候,將他和 NastyManager 取消掉綁定就好
public class LeakActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NastyManager.getInstance().addListener(this); } @Override protected void onDestroy() { super.onDestroy(); NastyManager.getInstance().removeListener(this); } }
先來看看造成內(nèi)存泄漏的代碼
通過查看Toast類的源碼可以看到,Toast類內(nèi)部的mContext指向傳入的Context。而ToastUtils中的toast變量是靜態(tài)類型的,其生命周期是與整個(gè)應(yīng)用一樣長(zhǎng)的,從而導(dǎo)致activity得不到釋放。因此,對(duì)Context的引用不能超過它本身的生命周期。
/** * 吐司工具類 避免點(diǎn)擊多次導(dǎo)致吐司多次,最后導(dǎo)致Toast就長(zhǎng)時(shí)間關(guān)閉不掉了 * @param context 注意:這里如果傳入context會(huì)報(bào)內(nèi)存泄漏;傳遞activity..getApplicationContext() * @param content 吐司內(nèi)容 */ private static Toast toast; @SuppressLint("ShowToast") public static void showToast(Context context, String content) { if (toast == null) { toast = Toast.makeText(context , content, Toast.LENGTH_SHORT); } else { toast.setText(content); } toast.show(); }
解決辦法
是改為使用 ApplicationContext即可,因?yàn)锳pplicationContext會(huì)隨著應(yīng)用的存在而存在,而不依賴于Activity的生命周期
5.1.0 靜態(tài)集合使用不當(dāng)導(dǎo)致的內(nèi)存泄漏有時(shí)候我們需要把一些對(duì)象加入到集合容器(例如ArrayList)中,當(dāng)不再需要當(dāng)中某些對(duì)象時(shí),如果不把該對(duì)象的引用從集合中清理掉,也會(huì)使得GC無法回收該對(duì)象。如果集合是static類型的話,那內(nèi)存泄漏情況就會(huì)更為嚴(yán)重。因此,當(dāng)不再需要某對(duì)象時(shí),需要主動(dòng)將之從集合中移除。
5.1.1 動(dòng)畫資源未釋放導(dǎo)致內(nèi)存泄漏
問題代碼
public class LeakActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_leak); textView = (TextView)findViewById(R.id.text_view); ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView,"rotation",0,360); objectAnimator.setRepeatCount(ValueAnimator.INFINITE); objectAnimator.start(); } }
解決辦法
在屬性動(dòng)畫中有一類無限循環(huán)動(dòng)畫,如果在Activity中播放這類動(dòng)畫并且在onDestroy中去停止動(dòng)畫,那么這個(gè)動(dòng)畫將會(huì)一直播放下去,這時(shí)候Activity會(huì)被View所持有,從而導(dǎo)致Activity無法被釋放。解決此類問題則是需要早Activity中onDestroy去去調(diào)用objectAnimator.cancel()來停止動(dòng)畫。
@Override protected void onDestroy() { super.onDestroy(); mAnimator.cancel(); }5.1.2 系統(tǒng)bug之InputMethodManager導(dǎo)致內(nèi)存泄漏
每次從MainActivity退出程序時(shí)總會(huì)報(bào)InputMethodManager內(nèi)存泄漏,原因系統(tǒng)中的InputMethodManager持有當(dāng)前MainActivity的引用,導(dǎo)致了MainActivity不能被系統(tǒng)回收,從而導(dǎo)致了MainActivity的內(nèi)存泄漏。查了很多資料,發(fā)現(xiàn)這是 Android SDK中輸入法的一個(gè)Bug,在15<=API<=23中都存在,目前Google還沒有解決這個(gè)Bug。
6.其他建議 6.0.1 盡量避免使用 static 成員變量
盡量避免使用 static 成員變量
如果成員變量被聲明為 static,那我們都知道其生命周期將與整個(gè)app進(jìn)程生命周期一樣。這會(huì)導(dǎo)致一系列問題,如果你的app進(jìn)程設(shè)計(jì)上是長(zhǎng)駐內(nèi)存的,那即使app切到后臺(tái),這部分內(nèi)存也不會(huì)被釋放。按照現(xiàn)在手機(jī)app內(nèi)存管理機(jī)制,占內(nèi)存較大的后臺(tái)進(jìn)程將優(yōu)先回收,如果此app做過進(jìn)程互保?;?,那會(huì)造成app在后臺(tái)頻繁重啟。當(dāng)手機(jī)安裝了你參與開發(fā)的app以后一夜時(shí)間手機(jī)被消耗空了電量、流量,你的app不得不被用戶卸載或者靜默。
架構(gòu)設(shè)計(jì)上要思考是否真的有必要這樣做,盡量避免。如果架構(gòu)需要這么設(shè)計(jì),那么此對(duì)象的生命周期你有責(zé)任管理起來。
關(guān)于其他內(nèi)容介紹 01.關(guān)于博客匯總鏈接1.技術(shù)博客匯總
2.開源項(xiàng)目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關(guān)于我的博客我的個(gè)人站點(diǎn):www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡(jiǎn)書:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽書:http://www.ximalaya.com/zhubo...
開源中國(guó):https://my.oschina.net/zbj161...
泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault頭條:https://segmentfault.com/u/xi...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77192.html
摘要:然而,中依然有可能發(fā)生內(nèi)存泄漏。所以你的安卓快速定位解決內(nèi)存泄漏掘金昨天是個(gè)好日子,程序員的節(jié)日,在這里給所有的程序員送上一份遲到的祝福。應(yīng)用內(nèi)存泄漏的定位分析與解決策略掘金,大家好,我是。 Android 性能優(yōu)化之巧用軟引用與弱引用優(yōu)化內(nèi)存使用 - Android - 掘金前言: 從事Android開發(fā)的同學(xué)都知道移動(dòng)設(shè)備的內(nèi)存使用是非常敏感的話題,今天我們來看下如何使用軟引用與弱...
閱讀 1098·2021-09-22 15:19
閱讀 1715·2021-08-23 09:46
閱讀 2238·2021-08-09 13:47
閱讀 1416·2019-08-30 15:55
閱讀 1421·2019-08-30 15:55
閱讀 1981·2019-08-30 15:54
閱讀 2809·2019-08-30 15:53
閱讀 719·2019-08-30 11:03