1 getApplicationContext分析

该方法为contextImpl类的方法,返回一个ApplicationContext。方法代码为:

public Context getApplicationContext() {

return (mPackageInfo != null) ?

mPackageInfo.getApplication() : mMainThread.getApplication();

}

1.1 mPackageInfo.getApplication()分析

如果mPackeageInfo对象(LoadedApk类,全局唯一)不为空,就调用mPackageInfo的getApplication方法。该方法返回mPackageInfo对象中的mApplication对象。LoadedApk类中的mApplication只在一个地方被赋值:

public Application makeApplication(boolean forceDefaultAppClass,

Instrumentation instrumentation) {

if (mApplication != null) {

return mApplication; //如果mApplication不为空,就直接返回该值,说明android只允许一个APK含有一个application对象

}

//否则就创建一个Application对象

Application app = null;

String appClass = mApplicationInfo.className;

if (forceDefaultAppClass || (appClass == null)) {

//如果app类名为空,或者指定要求使用默认app类名,就使用这个类名

appClass = "android.app.Application";

}

//开始新建一个application对象

try {

java.lang.ClassLoader cl = getClassLoader();

//首先创建一个ContextImpl对象

ContextImpl appContext = new ContextImpl();

appContext.init(this, null, mActivityThread); //初始化

app = mActivityThread.mInstrumentation.newApplication(

cl, appClass, appContext);

appContext.setOuterContext(app);

} catch (Exception e) {

……

}

//将此app加入到mAllApplications链表中

mActivityThread.mAllApplications.add(app);

mApplication = app; //这里完成给mApplication赋值

…….

return app;

}

通过上面的分析,可以知道mPackageInfo.getApplication()方法返回当前APK的唯一的Application对象。

1.2 mMainThread.getApplication()分析

如果mPackeageInfo对象为空,就调用此方法。关于mPackeageInfo相关知识,目前还没分析透,待分析完全之后补充。

mMainThread为ActivityThread类,所以我们需要去ActivityThread.java中找寻答案。该类的getApplication方法返回mInitialApplication对象,此对象也是Application类。同样的分析方法,我们去探寻该对象是如何被赋值的。

在ActivityThread类中共有两个地方对其进行了赋值,第一处的代码如下:

private void handleBindApplication(AppBindData data) {

……

try {

// If the app is being launched for full backup or restore, bring it up in

// a restricted environment with the base application class.

Application app = data.info.makeApplication(data.restrictedBackupMode, null);

mInitialApplication = app;
    }

……

}

显然mInitialApplication对象是通过makeApplication方法创建的,所以这里的mInitialApplication与mPackageInfo.getApplication()方法返回的Application是同一个对象。同时需要说明一下handleBindApplication函数。该函数会在应用程序第一次启动时调用。具体点说就是:在启动应用程序时ActivityManagerService类中的onTranct方法会调用ActivityThread.bindApplication方法,此方法有两种参数(一为applicationInfo,二为其他相关函数);在bindApplication中会根据这两种参数构建一个AppBindData对象data,然后以此对象为参数调用sendMessage(int what = H.BIND_APPLICATION, Object m = data;过后系统就会在消息处理函数ActivityThread.handleMessage(int what)中调用handleBindApplication(AppBindData data)创建ApplicationContext对象。

另一处的代码如下:

private void attach(boolean system) {

if (!system) {

……

} else {//如果是系统进程,那么就调用以下代码

// Don't set
application object here -- if the system crashes,

// we can't
display an alert, we just want to die die die.

android.ddm.DdmHandleAppName.setAppName("system_process",

UserHandle.myUserId());

try {

mInstrumentation =
new Instrumentation();

ContextImpl context = new ContextImpl();

context.init(getSystemContext().mPackageInfo, null, this);

Application app =
Instrumentation.newApplication(Application.class, context);

mAllApplications.add(app);

mInitialApplication = app;

app.onCreate();

} catch
(Exception e) {

throw new
RuntimeException(

"Unable to instantiate Application():" + e.toString(), e);

}

}

}

对比此处红色部分的代码,和上面makeApplication方法的代码,可以发现两者其实都是创建一个Application对象。不过attach方法只在FrameWork进程(system_server)启动时调用,应用程序运行时并不会调用此方法。所以这里可以忽略。

总之,对应用程序而言getApplicationContext方法返回的都是应用程序的唯一ApplicationContext。

2 getBaseContext分析

此方法在ContextWrapper类中定义。代码如下:

public Context getBaseContext() {

return mBase;

}

这里的mBase就是一个Context对象,getBaseContext()
返回由ContextWrapper类的构造函数指定或attachBaseContext ()设置的Context,SDK文档很少,不推荐使用。

3 Activity.this分析

Activity.this返回当前activity的context,这个context属于当前的activity,会随着activity的摧毁而摧毁。

4 getContext

该方法比较特殊,特殊的原因不是它复杂,而是它的不确定性。因为并不是每一个类都有该方法,也不是每一个类中该方法的作用均相同。如在android.view类,它就返回当前view所运行的context,一般情况下是当前的activity的context。而在contentProvider类中,该方法返回的是ApplicationContext(在ActivityThread.installProvider中可以知道)。所以该方法的返回值要根据具体情况具体分析。

总结

了解了所有的获取context相关的函数过后,我们就可以很容易的理解下面的问题了:

this: 当前activity的context,生命周期为当前activity的生命周期。

This.getApplicationContext:返回整个应用程序的application
context,生命周期为整个应用程序。

get****Context各个方法分析的更多相关文章

  1. 【转】第7篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:全自动注册与反射方法分析

    作者: 牛A与牛C之间 时间: 2013-12-12 分类: 技术文章 | 2条评论 | 编辑文章 主页 » 技术文章 » 第7篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  2. 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件

    博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...

  3. c# AOP编程:Context与方法拦截

    之前做AgentBooking时候,遇到两个问题比较棘手,一个是异常的传递与捕获:如何可以合理地在层层代码调用中统一传递并统一捕获异常.因为如果有一个做法,可以地方统一处理异常,可以使代码减少很多tr ...

  4. SpringBoot框架——从SpringBoot看IoC容器初始化流程之方法分析

    目录 一.概观Spring Boot 二.Spring Boot应用初始化 2.1 初始化入口 2.2 SpringApplication的run方法 2.3 方法分析 三.容器创建与初始化 3.1 ...

  5. 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析

    前篇博客LZ已经分析了ReentrantLock的lock()实现过程,我们了解到lock实现机制有公平锁和非公平锁,两者的主要区别在于公平锁要按照CLH队列等待获取锁,而非公平锁无视CLH队列直接获 ...

  6. php模拟登陆的两种实现方法分析

    php模拟登陆的实现方法分析 本文实例分析了php模拟登陆的实现方法.分享给大家供大家参考.具体分析如下: php模拟登陆的实现方法,这里分别列举两种方法实现模拟登陆人人网.具体实例代码如下: 1)使 ...

  7. Servlet生命周期中的service方法分析

    问题ServletLifeCycle中的service方法内,有super.service(request, response); 会执行this.doGet(HttpServletRequest r ...

  8. KCF目标跟踪方法分析与总结

    KCF目标跟踪方法分析与总结 correlation filter Kernelized correlation filter tracking 读"J. F. Henriques, R. ...

  9. Android 缓存目录 Context.getExternalFilesDir()和Context.getExternalCacheDir()方法

    一.基础知识 应用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的.大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中.这样当该应用被卸载 ...

随机推荐

  1. C# 运用作用域

    前面已经展示了一些在方法内部创建变量的例子.变量从定义了它的语句开始存在,同一个方法内的后续语句可以使用该变量.换言之,变量只能在创建了之后才能使用.方法执行完毕后,变量也会彻底消失. 假如一个变量能 ...

  2. oc block排序

    NSArray *sortArr=[arr sortedArrayUsingSelector:@selector(compareWithClassAndName:)]; //数组排序--block N ...

  3. Shell脚本使用汇总整理——mysql数据库5.7.8以后备份脚本

    Shell脚本使用汇总整理——mysql数据库5.7.8以后备份脚本 Shell脚本使用的基本知识点汇总详情见连接: https://www.cnblogs.com/lsy-blogs/p/92234 ...

  4. 服务发现与注册-Eureka

    1.搭建 创建一个Springboot项目,添加依赖 <dependencies> <!--添加Eureka服务器端依赖--> <dependency> <g ...

  5. Python知识点入门笔记——特色数据类型(元组)

    元组(tuple)是Python的另一种特色数据类型,元组和列表是相似的,可以存储不同类型的数据,但是元组是不可改变的,创建后就不能做任何修改操作. 创建元组 用逗号隔开的就是元组,但是为了美观和代码 ...

  6. Poj3061Subsequence

    A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, a ...

  7. 快速排序算法(C)

    sort快排函数的基本版,效率n*logn,快排的完全版就是在递归之中夹杂对序列的预判断,最优的选择排序方法,快速排序算法只是其中之一. 简单的说明一下快速排序的思想,对于一个数列,首先选择一个基数( ...

  8. 03018_监听器Listener

    1.什么是监听器? (1)监听器就是监听某个对象的状态变化的组件: (2)监听器的相关概念 ①事件源:被监听的对象------三个域对象:request.session.ServletContext ...

  9. day10 消息队列,多进程和多线程以及协程,异步IO,事件驱动等

    回顾一下线程和进程 线程与进程的区别 守护线程: 队列: 两种方式: 先进先出  # 后入先出   #卖水果,后来的来的是新的 生产者消费者模型: 生产包子, 吃包子 事件 event: 红绿灯模型 ...

  10. CentOS6.5创建yum源

    昨天给布置个新的需求,做一个Yum仓库,要求是HTTP式的,在某个服务器上搭建个Yum仓库,能让其它的机器有了这个机器的.repo仓库文件后就可以从本地下载安装软件,以前都是下载后直接yum inst ...