[转载]Andriod中的Context理解与分析(1)-Android开发进阶&经验分享-eoe Android开发者社区_Android开发论坛 – Powered by Discuz!.
大家在应用程序开发的时候会经常遇到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的关系
大致流程如下
Andriod中的Context理解与分析相关链接
(1)http://www.eoeandroid.com/thread-312457-1-1.html
(2)http://www.eoeandroid.com/thread-312978-1-1.html
(3)http://www.eoeandroid.com/thread-312979-1-1.html