应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash
当一个对象已经不需要再使用了,本该被回收时,而另外一个正在使用的对象持有它的引用从而导致它不能被回收,这就导致本该被回收的对象不能被回收而停留在堆内存中,导致内存泄漏
内存泄漏是造成内存溢出的主要原因之一,因此在开发中应避免内存泄漏。
单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。
/** * 1、传入的是application的Context:这将没有任何问题,因为单例的生命周期和Application的一样长 ; * 2、传入的是Activity的Context:当这个Context所对应的Activity退出时,由于该Context和Activity * 的生命周期一样长(Activity间接继承于Context),所以当前Activity退出时它的内存并不会被回收, * 因为单例对象持有该Activity的引用,从而造成内存泄漏。 */public class AppManager { PRivate static AppManager instance; private Context mContext; private AppManager(Context context){ mContext = context; } public static AppManager getInstance(Context context) { if (instance == null) { synchronized (instance){ if(instance!=null){ instance = new AppManager(context); } } } return instance; }}非静态的内部类会持有外部类的一个隐式引用
/** * 非静态内部类持有外部类的隐式引用 * 而用该非静态内部类创建 静态的实例 * 该实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用 */public class WorkActivity extends JYActivity{ private static PersonBean person = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(person!=null){ person = new PersonBean(); } //... } class PersonBean{ //... }}Handler的使用编码不规范即有可能造成内存泄漏
/** * 非静态内部类持有外部类的隐式引用 * 由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用 * 消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时, * 消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用 * mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏 */public class WorkActivity extends JYActivity{ private TextView tvShow; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); tvShow.setText(msg.arg1+"测试"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvShow = (TextView) this.findViewById(R.id.tv_item); loadData(); } private void loadData() { Message msg = mHandler.obtainMessage(); mHandler.sendMessage(msg); }}正确写法
/** * 非静态内部类持有外部类的隐式引用 * 创建静态的内部类,弱引用Activity,从而可以持有Activity实例来做更新UI操作 * 在onDestroy方法中移除消息队列中的消息,从而更好的避免了内存泄漏 * */public class WorkActivity extends JYActivity{ private TextView tvShow; private MyHandler mHandler = new MyHandler(this); public static class MyHandler extends Handler{ private WeakReference<Context> wrf; public MyHandler(Context context){ wrf = new WeakReference<Context>(context); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); WorkActivity temp = (WorkActivity) wrf.get(); if(temp!=null){ temp.tvShow.setText(msg+"msg"); } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvShow = (TextView) this.findViewById(R.id.tv_item); loadData(); } private void loadData() { Message msg = mHandler.obtainMessage(); mHandler.sendMessage(msg); } @Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); }}对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
属性动画未在onDestory中停止,造成动画一直播放下去(即使在界面上看不到动画效果),活动的view被动画持有,view持有Activity的引用,最终导致Activity无法释放,造成内存泄漏
新闻热点
疑难解答