——————test1
new
AsyncTask<
void
,
void
=
""
>() {
@Override
protected
Void doInBackground(Void... params) {
SystemClock.sleep(
10000
);
return
null
;
}
}.execute();
——————test2
new
Thread(
new
Runnable() {
@Override
public
void
run() {
SystemClock.sleep(
10000
);
}
}).start();
上面的异步任务和Runnable都是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成,
那么将导致Activity的内存资源无法回收,造成内存泄漏。正确的做法还是使用静态内部类的方式,如下:
static class
MyAsyncTask
extends
AsyncTask<
void
,
void
=
""
> {
private
WeakReference<context> weakReference;
public
MyAsyncTask(Context context) {
weakReference =
new
WeakReference<>(context);
}
@Override
protected
Void doInBackground(Void... params) {
SystemClock.sleep(
10000
);
return
null
;
}
@Override
protected
void
onPostExecute(Void aVoid) {
super
.onPostExecute(aVoid);
MainActivity activity = (MainActivity) weakReference.get();
if
(activity !=
null
) {
//...
}
}
}
static
class
MyRunnable
implements
Runnable{
@Override
public
void
run() {
SystemClock.sleep(
10000
);
}
}
//——————
new
Thread(
new
MyRunnable()).start();
new
MyAsyncTask(
this
).execute();
这样就避免了Activity的内存资源泄漏,当然在Activity销毁时候也应该取消相应的任务AsyncTask::cancel(),避免任务在后台执行浪费资源。
一些建议
1、对于生命周期比Activity长的对象如果需要应该使用ApplicationContext
2、在涉及到Context时先考虑ApplicationContext,当然它并不是万能的,对于有些地方则必须使用Activity的Context
3、对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏
4、对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
将内部类改为静态内部类 静态内部类中使用弱引用来引用外部类的成员变量
5、对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null
6、保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期