获取context对象主要有四种方法:
1.view.getContext,返回当前View对象的context对象,通常是当前正在展示的Activity对象。
2.Activity.getApplicationContext,获取当前Activity所在的进程的context对象,通常我们使用context对象时,要优先考虑这个全局的进程context.
3.ContextWrapper.getBaseContext():用来获取一个contextWrapper进行装饰之前的context,可以使用这个方法,这个方法在实际开发中使用并不多,不建议使用。
4.Activty.this 返回当前的Activity的实例,如果是UI控件需要使用Activity作为context对象,但是默认的Toast实际上使用ApplicationContext也可以。
getApplication()和getApplicationContext()区别
Application本身就是一个context,获取getApplicationContext()得到的结果就是Application本身的实例,getApplication()方法的语义性非常强,一看就是知道就是获取Application
实例,但是这个方法只有在Activity和service中才能调用的到。那么也许在绝大多数情况下我们都是在Activity或者Service中使用Application的,但是如果在其他场景,比如BroadcastReceiver也想获得Application的实例,这时就可以借助getApplicationContext()方法。
错误的单例模式:
public class Singleton {
private static Singleton instance;
private Context mContext;
private Singleton(Context context) {
this.mContext = context;
}
public static Singleton getInstance(Context context) {
if (instance == null) {
instance = new Singleton(context);
}
return instance;
}
}
这是一个非线程安全的单例模式,instance作为静态对象生命周期要长于普通的对象,其中也包含Activity,假如Activity a 去getInstance获得instance对象,传入this,常驻内存的singleton保存
传入的对象,并一直持有,即使Activity被销毁掉,但它的引用还存在于一个Singleton中就不可能被GC掉,这样就导致了内存泄漏。
private static Drawable mDrawable;
....
ImageVIew iv = new ImageView(this);
mDrawable = getResoures().getDrawable(R.drawable.ic_launcher);
iv.setImageDrawable(mDrawable);
ImageView保存了mDrawable的引用,而ImageView传入的this是MainActivty的mContext,因为被static修饰的mDrawable是常驻内存的,MainActivity是它的间接引用,MainActivity被销毁时,也不能被GC掉,导致内存泄漏。
正确的用法:
1.当Application的context能搞定的情况下,并且生命周期长的对象,优先使用Application的context.
2.不要让生命周期长于Activity的对象持有到Activity的引用。
3.尽量不要再Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。