如果是想认真学习的话,请先不要看以下内容,此记录只是为加深记忆,可能会有错误的地方,以免有误导。
学习转载链接:https://blog.youkuaiyun.com/u014674558/article/details/62234008
App常见内存泄漏以及解决方法
1、非静态内部类,静态实例化
/**
* 自定义实现的Activity
*/
public class MyActivity extends AppCompatActivity {
/**
* 静态成员变量
*/
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() {
}
}
}
内部类InnerClass隐式持有外部类MyActivity的引用,在MyActivity的onCreate方法中调用innerClass = new InnerClass();
innerClass会在MyActivity创建的时候就有了它的引用,而innerclass是静态类型,不会被垃圾回收,MyActivity在执行onDestory方法的时候由于被innerClass持有引用而无法被回收,所以这样MyActivity就总是被innerClass持有而无法回收造成内存泄漏
2、不正确的使用Context对象,造成内存泄漏
比如在Android帮助类中,会有很多引用Context
/**
* 自定义单例对象
*/
public class Single {
private static Single instance;
private Context context;
private Object obj = new Object();
private Single(Context context) {
this.context = context;
}
/**
* 初始化获取单例对象
*/
public static Single getInstance(Context context) {
if (instance == null) {
synchronized(obj) {
if (instance == null) {
instance = new Single(context);
}
}
}
return instance;
}
}
解决方法:使用全局的Context或者context.getApplication();
3、使用handler异步消息通信
日常开发中我们通常这样定义Handler对象:
/**
* 定义Handler成员变量
*/
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
dosomething();
}
};
这样存在一个隐藏问题:在Activity中使用Handler创建的匿名内部类会隐式持有外部Activity对象,当子线程使用Handler暂时无法完成异步任务时,handler对象无法销毁,同时隐式持有的activity以及相关的组件与资源文件同样无法销毁,在成内存泄漏。我们普通的handler,平时使用时也是可以不用考虑这些,但是在子线程中有耗时操作通知UI时,要考虑这一点
解决方法:
使用静态变量定义handler,静态变量无法操作activity中的对象,所以需要在handler对象中添加一个对activity的弱引用
static MyHandler handler = new MyHandler (this) {
@Override
public void handleMessage(Message msg) {
dosomething();
}
};
static class MyHandler extends Handler {
WeakReference<Activity > mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) {
mImageView.setImageBitmap(mBitmap);
}
}
}
最后在onDestory方法中将后面的消息移除 handler.removeCallbackAndMessages(null);
4、使用了属性属性动画或循环动画
在Activity中使用了属性循环动画,在onDestory()方法中未正确停止动画
5、使用资源文件结束之后未关闭
在使用一些资源性对象(比如Cusor,File,Stream,ContentProvider等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存,它们的缓冲不仅存在于java虚拟机中,还存在与java虚拟机外。如果我们仅仅是把它们设置为null,而不去close关闭,仍然会造成内存泄漏
6、Bitmap使用不当
bitmap对象使用的内存比较大,当我们不再使用bitmap对象的时候一定要执行recycle方法,执行该方法不会立即释放掉,只是通知虚拟机该bitmap可以被recycle了
7、一些框架使用了注册方法而未反注册
比如我们常用的时间总线框架-EventBus,当我们需要注册某个Activity时,需要在onCreate中:
EventBus.getDefault().register(this);
则EventBus对象持有该Activity的引用,及时onDestory,仍然无法回收,需要在onDestory方法中调用
EventBus.getDefault().unregister(this);
8、集合中的一些方法的错误使用
比如list列表静态化,只是添加元素而不再使用时不清除元素;
map对象只是put,没有remove操作等;