Android framework : 对context的理解

慕课网 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得初始化流程

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值