context在Android中比较重要,贯彻全文。context是一个抽象类,ContextImpl是它的实现类,ContextWarapper是context的子类,在里面用到了复合模式,传入一个context的对象,把实现类ContextImpl传了进去。
Context包括了 activity service Application ,BroadcastReceiver和内容提供者里面的参数context也可以使用。
context的作用的很多,activity作为它的的子类,作用范围最广,有一些功能只有activity独有。比如 dialog AlertDialog的显示,启动另外一个activity以及获取一个布局转换器。
dialog AlertDialog必须依附于activity才能显示,此时dialog 显示后,activity仍然保持在onResume()之后,onPause()之前,dialog可以看做是activity的一部分,构造参数里面传入的上下文只能是activity,其他的都无用,并且会报错。
从一个页面跳转到另外一个页面,启动startActivity()方法,也只能activity独有。
布局转换器LayoutInflater的创建方法最终都是调用一个方法,LayoutInflater LayoutInflater =(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
这里的context也只能是activity,把xml转换为layout对象,显示在UI上面。
有一些功能是所有上下文通用,比如send 一个广播,弹出一个toast 以及 resource资源获取,这个简单,没必要什么说的。
再有就是支持一部分功能的,比如启动一个service和绑定服务。Application activity service 以及内容提供者都支持,广播里面的context参数不支持。
上下文的另一种用法就是被持有对象引用, 该对象生命周期比较长,避免因此产生的内存泄漏。如一个单例模式,构造方法有context,就要谨慎了
public class Student {
private Context context;
private static Student mStuSingle;
private Student(Context context) {
this.context = context;
}
public static Student getStuSingle(Context context){
if(mStuSingle == null){
synchronized (Student.class) {
if(mStuSingle == null){
mStuSingle = new Student(context);
}
}
}
return mStuSingle;
}
}
如果传入的是一个activity,那么Studnet对象会一直持有activity的引用,即使activity调用的finish()方法,activity也不会关闭被回收,这样就会造成activity不能被回收,长时间后造成内存泄漏。此时关键是控制好上下文的 生命周期,选择生命周期比较长的Application就可以了,它是全局的单例的。