慕课网 framework 笔记
3-4 谈谈对context的理解
考察:
了解context的作用
熟悉context初始化流程
深入理解不同应用组件之间context的区别
回答问题:
1,应用里多少个context,不同context之间由上面区别
2,Activity里面的this和geteBaseContext有什么区别
3,getAppliccation和getApplicationContext有什么区别
4,应用组件的构造,onCreate,attachBaseContext调用顺序
1,context的作用
看看context类的定义,它是一个抽象类,不是接口,这个要注意
看看注释,有助于理解这个类,
//interface to global information about an application environment.
//this is an abstract class whose implimentation is provided by the android system.
//it allows access to application-specific resources and classes,as well as up-calls for application-level operations
//such as launching activities, boradcasting and receiving intents,etc.
//这是一个关于应用环境的全局信息的接口,不好理解
//这是一个抽象类,它的信息是由android系统提供的,
//有了它,你就可以访问AP特定的资源和类,而且还可以发起AP层的调用如启动activity,发送广播,接收intents等
//看看context的抽象函数在,这里选了几个 常用的函数
public abstract class Context{
public abstract Resources getResources(); //访问资源
public abstract Object getSystemService(String name); //访问系统服务
public abstract void startActivity(Intent intent); //启动Acitivity
public abstract void sendBroadcast(Intent intent); //发送广播的
......
}
//以上都是抽象函数,实现在ContextImpl里面
//看看类的全局变量,全局变量涉及了类的方方面面,
class ContextImpl extends Context{
final ActivityThead mMainThread; //应用的核心类
final LoadedApk mPackageInfo; //安装包的信息
//系统资源相关
private final ResourcesManager mResourcesManager;
private final Resource mResources;
private Resources.Theme mTheme = null; //主题相关
private PackageManager mPackageManager; //包管理
final Object[] mServiceCache =
SystemServiceRegistry.createServiceCache(); //系统服务的缓存
}
正是因为有了context,这些应用组件才有意义,他们才能访问系统服务,系统资源
如果没有context,Activity不过是普通的java对象,
就像皇帝,如果没有各种机构,它管不了这么大的江山,如果没有权利,皇帝也就是一个普通人,
如果Activity是皇帝,context就是权力,它有了权力,就可以调用各个资源。
2,context在哪里创建、》?
先了解有哪些context,也就是有哪些组件有自己的context:
Applicatoin,Activity,Service,
而广播和content provider没有自己的context'
先看Application context
Applicaton context跟着Application一起初始化的,而Application又是跟随AP进程的启动一起init的,
AP进程启动流程:
zygote fork->AP,AP启动后启动java类的入口函数(ActivityThread的main),这个函数会向AMS报告启动好了,
AMS收到后会下命令,让AP创建Application。
AP处理的函数:
private void handleBindApplication(AppBindData data){
//创建Application对象
Application app = data.info.makeApplication(...);
//执行它的onCreate回调
app.onCreate();
}
//看看怎么创建Application对象
public Application makeApplication(...){
//创建context,里面的实现就是new了一个ContextImpl(...)对象
ContextImpl appContext = ContextImpl.createAppContext(...);
Application app;
//创建Application对象,这里传了一个context进去,跟一下它
app = mActivityThread.mInstrumentation.newApplication(appContext);
return app;
}
//创建Application
Application newApplication(ClassLoader cl, String className, Context context){
//用classload加载Applicatoin类
return newApplication(cl.loadClass(className), context);
}
Application newApplication(Class<?> clazz, Context context)
{
//newInstance调用类的构造函数,得到Application对象,
Application app = (Application)clazz.newInstance();
//再给Application对象附上context
//这里面其实调用的是attachBaseContext(),
app.attach(context);
return app;
}
//要搞清楚attachBaseContext,要了解Application类的继承关系:
//application继承自ContextWrapper
public class Application extends ContextWrapper{
...
}
//ContextWrapper又继承自context,
public class ContextWrapper extends Context{
Context mBase;
//设置了ContextWrapper的mBase对象,mBase也是一个context,
//ContextWrapper自己就是Context,为什么又包了一个context?
protected void attachBaseContext(Context base){
mBase = base;
}
public Context getBaseContext(){
return mBase;
}
}
//ContextWrapper自己就是Context,为什么又包了一个context?
//其实ContextWrapper中关于context的调用都转手交给了mBase对象,
//这是典型的静态代理
public class ContextWrapper extends Context{
Context mBase;
@Override
public Resources getResources(){
return mBase.getResources();
}
@Override
public Object getSystemService(String name){
return mBase.getSystemService(name);
}
@Override
public void startActivity(Intent intent){
mBase.startActivity(intent);
}
}
如果我们通过反射换掉了mBase对象的话,
如在调用getSystemService时,就会跳转到另一个context实现,就可以对返回的SystemService管理对象做一些手脚,
这个机制一般插件会用到。
Application的结论:
继承关系:Application <- ContextWrapper <- Context
调用顺序:<init>(Application的构造函数) => attachBaseContext(设置context) =》onCreate
ContextWrapper里会包含一个Context,调用都会委托给它,就是mBase吧
2,Activity的Context怎么初始化?
它是跟着Activity启动的时候一起init的
看看Activity启动:
private Activity performLaunchActivity(){
Activity activity = null;
//看后面
activity = mInstrumentation.newActivity();
//Application其实之前已经创建好了,这里直接返回就可以了
Application app = r.packageInfo.makeApplication();
//为Activity创建一个context:new ContextImpl(...)
Context appContext = createBaseContextForActivity(r, activity);
//把context赋给activity,
//attach里面会调用到attachbaseContext(context); 把context赋给Activity里面的mBase
//mBase是ContextWrapper里面的一个成员变量,用到了静态代理
activity.attach(appContext, app,...);
//走到了onCreate生命周期回调。
activity.onCreate();
return activity;
}
//newActivity和newApplication有一些类似,loadClass加载类,然后NewInstance调用构造函数创建一个对象
public Activity newActivity(ClassLoader cl, String className){
return (Activity)cl.loadClass(className).newInstance();
}
看到流程和Application类似:
创建组件对象,为组件创建context,把context赋给它,再调用组件的onCreate生命周期
3,说完了init流程,再看Activity的类继承关系
Activity和Application有些不同,它继承自ContextThemeWrapper,
public class Activity extends ContextThemeWrapper{...}
//比ContextWrapper多了一个 Theme,和主题有关
public class ContextThemeWrapper extends ContextWrapper{
//看看它的成员变量,都是和主题,界面有关, 因为Activity就是要显示界面的
//但是其他的与其他组件是一样的,比如Context的调用,最终都是要给ContextWrapper里面的mBase变量的
private int mThemeResource;
private Resources.Theme mTheme;
private LayhoutInflater mInflater;
private Configuration mOverrideConfiguiration;
private Resources mResources;
}
Activity的结论:
类继承关系:Activity <- ContextThememWrapper <- ContextWrapper,
Application是直接继承ContextWrapper的,但是Activity还要负责界面展示,所以它多了一个ContextThemeWrapper这一层,。
调用顺序:<init>(Activity的构造函数,创建context) -> attachBaseContext(把context赋值给Activity) ->onCreate
4,看看Service
Service与Application一样,也是继承自ContextWrapper的,他们都不需展示界面的,
public abstract class Service extend ContextWrapper{...}
service的初始化:
private void handleCreateService(CreateServiceData data){
Service service = null;
//第一步都是通过ClassLoader加载service的类,加载后newInstance调用构造函数,创建service对象
service = (Service) cl.loadClass(data.info.name).newInstance();
//创建context,里面就是new ContextImpl(...)
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
//为service准备Applicatoin,虽然叫makeApplication,但是其实只是返回之前已经创建好的Application对象。
Application app = packageInfo.makeApplication();
//把Context和Application全部赋给Service
//里面会调用attachBaseContext(context),作用和Application的一样,把Context赋给ContextWrapper里面的mBase
service.attach(context, app);
//低啊用service的onCreate生命周期回调
service.onCreate();
}
5,看看 广播
就是一个抽象类,也没有继承ContextWrapper ,也没有关于Context的成员变量,
只有一个onReceve函数,里面有一个参数context
public bastract class BoradcastReceiver{ public adstract void onReceive(Context context, Intent intent); .... }
如果广播是动态注册的,那context就是注册广播时用的context:context.registerReceiver
如果是静态注册,这也不是Application的context,。而是以Applicatoin为mBase的ContextWrapper,愿意后面讲。这里记结论。
6,看看contentProvider
它也没有继承ContextWrapper,但它有个context成员变量,
这是COntextProvider初始化的时候传进来的,传的Applicatoin 的context,
ContextProvider的初始化虽然是在Application的构造函数和AttachBaseContext之后,
但是它是在Application的onCreate之前调用的,
所以,ContextProvider的onCreate比Application的onCrreate早,这个要注意
public abstract class ContentProvider{ private Context mContext = null; .... }
回到我们的问题:
1,AP里面有多少个context,不同的context有什么区别?
Ap里面只有Application,Activity,Service有自己的context,
广播和ContextProvider是没有的,
所以有多少个context大家可以算一下,
Activity个数+Service个数+Application个数,Application是跟进程走的,所以它的context可能有多个。
区别:
Activity要显示UI,所以继承的是ContextThemeWraper,Applicatoin和service不需要显示,虽然继承是的ContextWrapper。
2,Acitivyt的this和getBaseContext有什么区别?
Activity就是继承context的,所以this是返回Activity自己,
getBaseContext返回的是ContextWrapper里面的mBase;
3,getApplication和getApplicationContext有什么区别?
都是返回Applicatoin对象,getApplicationContext是context的一个抽象函数,
getApplicatoin是Activity和service里面特有的,其他地方不能用,
如广播,onReceive()的第一个参数,拿到这个context是不能调用getApplication的只能调getApplicationContext,
4,应用组件的构造,onCreate,attachBaseContext调用顺序
先调用组件的构造函数,然后是attach context,最后onCreate
总结:
1,说清楚Context的作用:
是应用组件的上下文,有了context,应用组件才能方便的访问系统资源,调用系统服务,
2,AP里有那几个组件是有自己的context的,他们有什么区别,继承关系是怎么样的
3,说下context得初始化流程