Andriod中的Context理解与分析

大家在应用程序开发的时候会经常遇到Context,也经常使用,那怎么理解Context呢?

在做Web开发的时候也会有一个Context,一般翻译“成上下文”,也就是代表整个程序运行的环境,直到进程结束之后。
那么Android中的Context是不是这样的呢?Android中不是,Android中的Context可以理解成场景,场景是什么什么意思呢?
如果把Android程序的整个运行期间成为一个电影的话,那么一个Activity或者一个Service就可以称之为一个场景,一个电影
可以包括多个场景。
咱们先看下Context相关的继承结构:


从继承关系可以看出,Activity和Service都是基于Context实现的。
Activity不仅基于Context实现,并且还实现了一些重要的其他接口。从设计的角度,继承的才是类的本质,接口仅仅是未来扩充功能。
Activity和Service本质是一个Context,然后扩充了一些功能之后,要么成为Activity,要么成为Service。
而Application也可以认为是为了做一些操作方便,才继承的Context。

也就是说有多少个Activity和Service就有多少个场景,也就是有多少个Context对象(Application也算一个)。

这个Context仅代表一个Activity或者一个Service(Application除外)。

Context的真正实现类是ContextImpl,ContextWraper根据名称可以看出是Context的包装类,在ContextWrap中包装
了ContextImpl,调用ContexWraper的时候也就调用到了ContextImpl的方法。ContextWraper提供了set  ContextImpl
的方法attachBaseContext()。

Activity最终是包含界面的所以他继承了ContextThemeWraper,有Theme这个单词,这个Theme是AndroidMenifest.xml中
的Theme标签对应的Theme。因为Service和Application都不包含界面,就没必须继承ContextThemeWraper了,只需继承
ContextWraper即可。


Application对应的Context

每个应用程序在第一次启动的时候都会产生一个Application,这个Application在整个程序运行期间是唯一的,程序员们可以
根据自己程序的需要重写这个函数,只需继承一下,在需在AndroidMenifest.xml文件的<application>标签上配置下类全名即可,
不配置的话会使用默认的Application。(因为全局是唯一的,可以使用它做一些数据库缓存或者数据传递地方)。

程序第一次启动时,ActivityManagerService会经过ApplicationThread的代理类
远程调用真正的ApplicationThread的bindApplication()方法(这个里把ActivityManagerService当成了Binder客户端,
在ActivityThread中的ApplicationThread对象才是真正的Binder服务端)。

ApplicationThread这个类定义在ActivityThread类文件中。
             代码片段1

这些参数都是从ActivityManagerService通过IPC(Binder方式)传递过来的。如果要在Binder方式中传递对象的话,那么这个类
要实现Parceable接口,看下第一个参数appInfo,通过名字可以知道,是代表应用程序的信息类,这个类按道理肯定实现了
Parceable接口,不错确实实现了这个接口。看下这个类的声明。
、、
           代码片段2

还继承自PackageIntemInfo,PacageItemInfo就是通过AndroidMenifest.xml文件解析出的啊<application>标签中的内容
             代码片段3

从547行开始看,此处创建了一个AppBindData对象data,然后把从ActivityManagerService远程传递过来的参数赋值给data对象,
其中第549行就包括了appInfo赋值给了data对象的appInfo。
咱们看看AppBindData类到底是什么样的,AppBindData是ActivityThread中的内部类。从下面的代码可以看出只是对传过来的参数进行
了简单的封装。
        代码片段4
我们再回到 代码片段1 中的558行其中参数中H.BIND_APPLICATION是继承自Handler的一个类的一个int常量,第二个参数就是刚封装的数据类型data了。
继续代码

     代码片段5

继续代码

         代码片段6

重点就是what参数和obj参数。在1519行获得一个可回收利用的Message对象,然后把传递过来的消息发送到消息队列(1524行),‘
Looper一直在从消息队列里取消息。当取到刚发送的消息后,会回调Handler的handleMessage()方法,继续到H类中
先说明一下,ActivityThread创建时这个H的对象就已经创建好了,这个Handler属于UI线程(主线程)。
     代码片段7
那咱们还是去H这个类的handleMessage()方法吧
其中有个switch结构
H.BIND_APPLICATION对相应的处理如下:

         代码片段8
968行把msg中的obj强制转型成AppBindData,做为handleBindApplication(data)的参数继续执行

         代码片段9
3122行,把data赋值给了mBoundApplication

         代码片段10

3149行,调用getPacageInNocheck()构建一个LoadedApk对象,赋值给data.info。在这个调用中把LoadedApk对象存到了mPackages中。
这个LoadedApk对象,这个对象包含了更多的应用程序的信息。

         代码片段11
第3260行才是真正的使用反射创建一个Application对象,返回值赋值给mInitialApplication。
进入到Loaded.makeApplication()方法,如下
         代码片段12
454行:forceDefaultAppClass这个参数的意思是,是否强制使用系统提供的默认class类,即android.app.Application’
459行:创建了一个ContextImpl实例
461行:创建了一个Application实例,mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext)的具体实现如下:

         代码片段13

942行:继续调用重载的方法

        代码片段14
第958行是设置Application和Context的关联。

调用完整个方法,继续回到 代码片段12
463行设置Context和Application的关联。
片段12的代码继续执行到下面,把Application保存到LoadedApk中一份
      代码片段14
这方法执行完成之后回到 代码片段11继续执行
        代码片段15

在上面的方法中执行了Application的onCreat()方法
         代码片段16

程序员可以重载Application的onCreate()知道Application创建后的时机,然后做一些相应的操作。

以上就是说明了Application和Context的关系

大致流程如下

 

没完,待续.....
                
Activity对应的Context

Service对应的Context

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值