四种引用类型:
强引用,软引用,弱引用,虚引用;
软引用和弱引用的区别:
SoftReference在虚拟机内存不足时,将会回收它指向的对象;
WeakReference随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收
内存泄漏:
Android中的内存泄漏的原因是生命周期较长的对象持有生命周期较短的对象的引用,导致短生命周期的对象在较长生命周期内无法被回收;
1.单例造成的内存泄露
由于单例静态的特性,它的生命周期和整个应用一样长,如果这个单例持有一个Activity的强引用,就会导致内存泄漏:
class Singleton{
private static SingleInstanceTest sInstance;
private Context mContext;
private Singleton(Context context){
this.mContext = context;
}
public static SingleInstanceTest newInstance(Context context){...}
}
解决办法:如果可以的话尽量持有Application的引用
private Singleton(Context context){
this.mContext = context.getApplicationContext();
}
如果一定要持有Acitivity的话建议使用弱引用,避免静态变量引用过多实例
2.非静态内部类 / 匿名类
非静态内部类的特性:自动获得外部类实例的强引用,被调用时需要外部实例,生命周期可能长于外部类
常见的引发内存泄漏的有:
AscnyTask:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyAscnyTask().execute();
}
//这里改成静态的就ok了
class MyAscnyTask extends AsyncTask<Void, Integer, String>{
@Override
protected String doInBackground(Void... params) {
.....
}
}
}
3.Handler引起的内存泄漏:
public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Message message = Message.obtain();
mHandler.sendMessageDelayed(message, 10000);
}
}
内存泄漏原因:
被发送的Message都存在MessageQueue中,而每个Message都有Handler的引用,Handler作为Activity的匿名内部类又持有Activity的引用,所以消息在处理完之前Activity的内存都无法释放;
解决方式:
这里应该继承Handler实现一个静态内部类以防止内存泄漏;
或者可以通过调用removeCallbacksAndMessages方法移除Message
4.集合类移除无用对象:
5.需要手动关闭的对象:
try/catch/finally中网络文件等流的手动关闭:Http,File,ContentProvider,Bitmap,Url,Socket
内存抖动
堆空间即将装满,短时间内频繁触发临时变量的创建和回收的过程就是内存抖动。
所以要注意在循环体和onDraw方法中尽量避免创建临时变量。