1.单例模式
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
单例模式的静态特性使得实例的生命周期和Application一样长,如果某个对象的context传参构造单例模式,当对象不再使用而单例还持有该对象的引用不能被释放,导致内存泄漏。
解决办法:context用ApplicationContext
2.用非静态内部类创建静态实例
public class MainActivity extends AppCompatActivity {
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 {
//...
}
}
作用:防止重复创建资源。 泄漏原因:非静态内部类默认持有外部类的引用,静态实例与Application生命周期一样长 ,内部类使用完仍被静态实例持有,无法释放,Activity也无法释放,导致内存泄漏。
解决办法:每部类改为静态或者将内部类独立成为一个类以单例模式引用
3.Handler内存泄漏
public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//...
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadData();
}
private void loadData(){
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
}
}
Handler是非静态内部类,默认持有外部类引用,Activity结束时消息队列中消息没处理完,Message持有mHandler实例的引用,mHandler持有Activity的引用,导致Activity无法释放。
解决办法:创建Handler静态内部类,持有的对象使用弱引用
public class MainActivity extends AppCompatActivity {
private MyHandler mHandler = new MyHandler(this);
private TextView mTextView ;
private static class MyHandler extends Handler {
private WeakReference reference;
public MyHandler(Context context) {
reference = new WeakReference<>(context);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = (MainActivity) reference.get();
if(activity != null){
activity.mTextView.setText("");
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
loadData();
}
private void loadData() {
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
}
}
4.线程内存泄漏
异步任务和Runnable都是非静态内部类,默认持有外部类引用,Activity结束时异步任务没有结束导致不能释放内存。
解决办法:静态内部类
static class MyAsyncTask extends AsyncTask {
private WeakReference 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();
5. 资源未关闭
Cursor未关闭,Bitmap未回收,BraodcastReceiver,ContentObserver,File,Stream等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。