最近看了一下深入安卓内核,毫无安卓基础的我一头深入不可自拔,看的是云里雾里,第一遍看到一半左右似乎开始失去了效率。

现在开始第二遍,并对看过的重要知识点以个人的理解进行梳理(不免有错的地方,好心人请告知,我也会经常反复阅读与更新)

其实我个人理解的话,context是一个页面或者说是一个场景。

我想刚开始我们可以从UML图挖掘我们一些基础知识。

1 可以看出我们常用的activity和service都是继承或者间接继承的是ContextWrap类。

2 有所不同的是activity是通过contextThemeWrapper来的,其实也很好理解,因为activity是有页面的所以他需要一个主题。

Context类本身是一个纯abstract类,那ContextWrap是什么呢?从他的构造函数可以看出他是context的一个包装

public class ContextWrapper extends Context {
Context mBase; public ContextWrapper(Context base) {
mBase = base;
}

OK,一下子右边半边的类图我们已经清楚了。

接下来我们看左边的ContextImpl他往下没有子类,而从这个名字来看他应该是真正实现了context的所有抽象方法。

那么我们找一下再哪里有被调用?

我们发现代码在ActivityThread中的handleBindApplication()方法中,此方法内部调用了makeApplication方法里面恰好有new contextImpl()

public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
String appClass = mApplicationInfo.className;
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = new ContextImpl(); //创建contextImpl对象
appContext.init(this, null, mActivityThread); //进行初始化赋值,请注意第一个参数this是值得mPackageInfo对象
application app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
}
...
}

可见在创建context的时候会用到contextImpl类。

那么我们接下来看一下application、service、activity的创建过程我这边分别用/隔开,其实原理都是一样的。

1 AMS创建ApplicationInfo/Servicelnfo/Activitylnfo对象

2 AMS通过IPC调用的activeThread对象的bindApplication/scheduleCreateService/scheduleLaunchActivity方法将ApplicationInfo/Servicelnfo/Activitylnfo传入。

3 bindApplication/scheduleCreateService/scheduleLaunchActivity方法会将ApplicationInfo/Servicelnfo/Activitylnfo的值赋值给AppBindData/CreateServiceData/ActivityRecord

4 调用handleBindApplication/handleCreateService/handleLaunchActivity方法中的getPackageInfoNoChecked()方法为AppBindData/CreateServiceData/ActivityRecord的Info属性赋值PackageInfo

5 调用make方法创建对应的context

以上5个步骤分别是创建activity,application,service对象,注意packageInfo是一个全局的对象。context和package是多对一的关系

1 说简单点其实就是AMS需要把INFO信息传递给ActivityThread

2 activityThread将传入的Info信息包装一下成为自己的数据结构DATA

3 然后再去获取全局的PackageInfo对象装载到自己的DATA里

4 调用makeXXX进行创建

context的个数=service+activity+application(1个)

安卓context(一)的更多相关文章

  1. 安卓 Context 和 Application的关系

    1. 我开始一直不理解显式Intent中传一个this(当前的activity)是为什么.因为Intent里面的构造方法对应的只有 Context, Class.后面查资料才发现 Intent i = ...

  2. Android的Context && 安卓常用系统服务(当前运行包名/当前网络状态和开关网络/音频服务/马达服务) (转)

    转:http://blog.csdn.net/zhandoushi1982/article/details/8501773 Context字面意思上下文,位于framework 的android.co ...

  3. 安卓自定义组合控件--toolbar

    最近在学习安卓APP的开发,用到了toolbar这个控件, 最开始使用时include layout这种方法,不过感觉封装性不好,就又改成了自定义组合控件的方式. 使用的工具为android stud ...

  4. 放弃安卓原生TimePicker,选择wheelView打造更漂亮的时间get,以及动态拉伸输入框布局,这些,这里都有!

    最近公司要求的上线项目有这么一个需求,要写一个请假申请的页面,里面必须有请假开始时间,结束时间,还有一个请假原因. 于是想到时间选择嘛,官方不是有个DatePicker吗?额,是不是要DatePick ...

  5. android使用ImageLoader实现图片缓存(安卓开发必备)

    相信大家在学习以及实际开发中基本都会与网络数据打交道,而这其中一个非常影响用户体验的就是图片的缓存了,若是没有弄好图片缓存,用户体验会大大下降,总会出现卡顿情况,而这个问题尤其容易出现在ListVie ...

  6. 安卓第一次启动引导页使用ViewPager实现

    我们在安装某个APP的时候,基本都会有一个引导页的提示,他们可以打广告,或者介绍新功能的加入和使用说明等.一般都支持滑动并且下面有几个点,显示共有多少页和当前图片的位置,在IOS上这个实现起来比较简单 ...

  7. 安卓开发之ListAdapter(二)

    今天我们来学习一下ArrayAdapter: ArrayAdapter是安卓中最简单的适配器.使用ArrayAdapter(数组适配器),需要把数据源存 放至数组里面来显示. •构造函数: publi ...

  8. android安卓Sqlite数据库实现用户登录注册

    看了很多别人写的安卓SQlite数据的操作代码,一点也不通俗易懂,我觉得我写的不错,而且安卓项目也用上了,所以在博客园里保存分享一下!建立一个类 并继承SQLiteOpenHelper public ...

  9. 安卓中AIDL的使用方法快速入门

    1.AIDL是什么? AIDL全称是Android Interface Definition Language,即安卓接口定义语言. 2.AIDL是用来做什么的?(为什么要有AIDL) AIDL是用来 ...

随机推荐

  1. Java的感受

    感觉Java很重要,但是学起来好像并不比C语言简单.

  2. Rxjava+retrofit+mvp整合

    转载请标明出处: http://blog.csdn.net/forezp/article/details/52621898 本文出自方志朋的博客 最近在看Rxjava,写了一个简单的 demo整合了R ...

  3. 阿里云OSS图片上传plupload.js结合jq-weui 图片上传的插件

    项目中用到了oss上传,用的plupload,奈何样式上不敢恭维,特别是放在移动端上使用.于是自己把它移植到了jq weui的上传图片组件上. 更改:选择照片后确认即及时上传至oss服务器,不限制上传 ...

  4. MySql错误1045 Access denied for user 'root'@'localhost' (using password:YES)

    1.先停止mysql服务 2.进入mysql的安装路径,找到并打开my.ini文件,找到[mysqld],在该行下面添加 skip_grant_tables,也就是通知mysql,在登陆的时候跳过密码 ...

  5. egg- 配置

    1. model module.exports = app => { const { INTEGER, STRING, TEXT } = app.Sequelize; const User = ...

  6. linux安装openldap步骤

    目录 虚拟机环境:centos 7 一.环境准备 1.关闭 selinux firewalld 临时: setenforce 0  永久: vi /etc/sysconfig/selinux SELI ...

  7. 【c学习-1】

    #include<stdio.h> int main(){ int a,b,max; printf("请输入两个整数:"); //格式化输出函数 scanf(" ...

  8. swoole中swoole_timer_tick回调函数使用对象方法

    swoole_timer_tick的回调函数无法使用类似于array($this, 'method')来调用对象方法,所以我用一下方法变通了一下来调用 swoole_timer_tick(1000, ...

  9. Form表单提交,js验证

    Form表单提交,js验证 1,  Onclick() 2, Onsubmit() Button标签 input (属性 submit  button )标签 Input type=button    ...

  10. elasticsearch 5.x 系列之二 线程池的设置

    1,概述 每个Elasticsearch节点内部都维护着多个线程池,如index.search.get.bulk等,用户可以修改线程池的类型和大小,以及其他的比如reflesh, flush,warm ...