Context这个类我们每天都在接触,每天都在使用,那么他具体是什么呢?这个问题疑惑了我很长时间,看完郭霖大神对Context的分析,做出以下总结
Android四大组件Activity,BroadcastReceiver,Service,contentProvider这些组件并不能通过普通的new一下就能创建出实例了,而是要有他们各自的上下文环境,可以这么认为:Context是维持Android程序中各组件能够正常工作的一个核心功能类
Context的继承体系结构:
Context的直系子类有两个,一个是ContextWrapper(上下文功能的封装类)和ContextImpl(上下文功能的实现类),而ContextWrapper又有直接三个子类:Application、Service、和ContextThemeWrapper(带主题的封装类)--->Activity
结论:Context分为三种类型:Application、Activity、Service分别属于Context的一种,而他们的具体实现是由ContextImpl类去实现的
大多数情况下,Activity、Service、Application这三种类型的Context是可以通用的,但是比如启动Activity、弹出Dialog,Android是不允许Activity或Dialog凭空出现的,Activity的启动必须建立在另一个Activity的基础上,也就是形成任务栈。而Dialog必须在一个Activity上面弹出(除非是SystemAlert类型的Dialog),因此在这种场景下,我们只能使用Activity类型的Context,否则会出错。
一个应用程序中,Context的数量 = Activity数量 + Service数量 + 1(Application数量),一个应用程序可以有多个Activity,也可有多个Service,但是只能有一个Application
自定义Application:
自定义类继承Application类,注意:所有Context的方法调用,必须要在onCreate()方法中调用,不能在自定义类的构造方法中调用。这是因为在ContextWrapper中有个attachBaseContext()方法,这个方法会将传入的Context赋值给mBase对象,所有Context的方法都是调用这个mBase对象的同名方法,那么如果mBase没有被赋值,为null,调用其方法就会报空指针异常
在Application的onCreate()方法中初始化全局的变量数据是比较推荐的做法,但是如果还想把初始化的时间点提前到极致,可以重写attachBaseContext()方法
编写自定义Application注意事项:首先Application属于系统的组件,系统组件的实例是由系统来创建,Application全局只有一个,它本身就已经是单例,无需再用单例模式
/**
* Created by radish
*/
public class MyApplication extends Application {
private static MyApplication application;
public static MyApplication getInstance(){
return application;
}
@Override
public void onCreate() {
super.onCreate();
application=this;
}
}