getApplication()和getApplicationContext()区别
二者使用结果相同,我们写个代码分别打印二者返回结果,发现两个方法获取的是同一个对象。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Application application = getApplication();
Log.i("MainActivity", "打印getApplication:" + application);
Context pContext = getApplicationContext();
Log.i("MainActivity", "打印getApplicationContext:" + pContext);
}
}
结果
2019-12-06 14:35:40.082 4983-4983/google.voice.engine I/MainActivity: 打印getApplication:android.app.Application@3d34e67
2019-12-06 14:35:40.082 4983-4983/google.voice.engine I/MainActivity: 打印getApplicationContext:android.app.Application@3d34e67
区别
getApplication()是用来获取Application实例的,但是该方法只在Activity和Service中才能调用;在一些其他的地方,比如说当我们在BroadcastReceiver中也想获取Application实例,这时就需要使用getApplicationContext()方法
为什么是同一个对象呢 分析源码:
getApplicationContext我们知道是一个抽象方法,他的真正实现是在ContextImpl中:
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
再来看看getApplication方法(只存在于Activity和Service中):
public final Application getApplication() {
return mApplication;
}
那mApplication的赋值在哪?搜索一下,只有一个地方有赋值:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
.......
mApplication = application;
}
我看到了这里就觉得这两个方法返回的对象不一样,可是我们忽略了getApplicationContext这个方法,当mPackageInfo不为空和为空是分别调用了mPackageInfo.getApplication()和mMainThread.getApplication(),那getApplicationContext到底返回的东西跟mApplication有什么不同,来看看这两个方法,在LoadedApk.java中看到mPackageInfo.getApplication():
Application getApplication() {
return mApplication;
}
在LoadedApk也有一个mApplication,这个mApplication的赋值在LoadedApk的makeApplication:
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
...
if (mApplication != null) {
return mApplication;
}
Application app = null;
...
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
...
mActivityThread.mAllApplications.add(app);
mApplication = app;
...
}
看到首先是一个空判断(单例),为空的话新建了一个Application然后赋值给mApplication,我们再看看mMainThread.getApplication()返回了什么,在ActivityThread.java中:
public Application getApplication() {
return mInitialApplication;
}
再来看看mInitialApplication的赋值在哪里:
private void handleBindApplication(AppBindData data) {
...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...
}
我们又看到了makeApplication,至于data.info也是LoadedApk这个类,看到这里我们就一目了然了,绕来绕去结果都是同一个东西,只是可能创建的时机不同,一个是在LoadedApk,一个是在ActivityThread,不过最后我们发现这个getApplicationContext()返回的都是mApplication。
真相大白
这个命名就很有意思了,在LoadedApk我们看到了一个叫mApplication的东西,在Activity也有一个叫mApplication,那他们是不是有什么联系呢?来看看在Activity中mApplication的赋值,在attach方法中找到了它(方法中的其他参数我去掉了):
final void attach(Application application) {
mApplication = application;
}
也就是说等于调用attach方法时传入的application,那Activity的attach是在哪里调用呢,我们要来到反复提到的一个应用程序入口类ActivityThread,它有一个performLaunchActivity的方法,用来加载一个Activity,这里就有attach()的调用(我去掉了其他参数):
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
activity.attach(app);
...
}
我们发现又来了。。。熟悉的makeApplication(),r.packageInfo果然是LoadedApk类,最后殊途同归,又来到了这个单例,返回程序唯一的mApplication,还是一样的配方。。。
getApplication()和getApplicationContext()区别的更多相关文章
- Android 中this、 getApplicationContext()、getApplication()之间的区别
this:代表当前,在Activity当中就是代表当前的Activity,换句话说就是Activity.this在Activity当中可以缩写为this. getApplicationContext( ...
- Android Context 是什么?
andorid 开发(42) 版权声明:本文为博主原创文章,未经博主允许不得转载. [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] PS ...
- [Module] 03 - Software Design and Architecture
本篇涉及内容: ORM框架(无需再用contentprovider或者sqlitedatebasehelper之类的古董工具了) 规划各种业务Bean文件(配合ORM框架) 设计一个好的请求基类(Ba ...
- Android 中this、getContext()、getApplicationContext()、getApplication()、getBaseContext() 之间的区别
: 知之为知之,不知为不知是知也! 使用this, 说明当前类是context的子类,一般是activity application等; this:代表当前,在Activity当中就是代表当前的Act ...
- 从getApplicationContext和getApplication再次梳理Android的Application正确用法
原文地址http://blog.csdn.net/ly502541243/article/details/52105466 原文地址http://blog.csdn.net/ly502541243/a ...
- android开发中的 Activity 与 Context 区别与联系
Context 是 Application /Activity /Service的基类 Intent(Context , Class); Activity中的上下文Context是随着活动的产生而产生 ...
- Android源码分析-全面理解Context
前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...
- Android各种获取Context方法
首先讲一讲这四个函数的区别,后面还有我对context的一些理解区别如下所示: 原文链接http://stackoverflow.com/questions/6854265/getapplicatio ...
- Context详解
前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...
随机推荐
- 17JQuery高级
1. 动画 1. 三种方式显示和隐藏元素 1. 默认显示和隐藏方式 1. show([speed,[easing],[fn]]) 1. 参数: 1. speed:动画的速度.三个预定义的值(" ...
- redis缓存穿透-解决方案
上面的解决方案个人觉得时有误的,因为就算缓存了value的null值,后面的接口请求还是会判断走数据库,所以看解决方案二 解决方案二: https://blog.csdn.net/muyi_amen/ ...
- redis 加锁与释放锁(分布式锁)
使用Redis的 SETNX 命令可以实现分布式锁 SETNX key value 返回值 返回整数,具体为 - 1,当 key 的值被设置 - 0,当 key 的值没被设置
- Acwing-98-分形之城(递推,数学)
链接: https://www.acwing.com/problem/content/description/100/ 题意: 城市的规划在城市建设中是个大问题. 不幸的是,很多城市在开始建设的时候并 ...
- sublime text怎么格式化PHP代码
手动安装: 可能由于各种原因,无法使用代码安装,那可以通过以下步骤手动安装Package Control: 1.点击Preferences > Browse Packages菜单 2.进入打开的 ...
- Java多线程和并发(四),线程返回值获取方式和Callable接口
目录 1.主线程等待法 2.使用Thread类的join()阻塞当前线程,等待子线程执行完毕 3.通过Callable接口实现:通过FutureTask Or线程池获取 四.线程返回值获取方式和Cal ...
- BZOJ 3991: [SDOI2015]寻宝游戏 树链的并+set
Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可 ...
- confluence -- 命令行备份还原
备份:confluence每日凌晨2:00都在 /data/atlassian/application-data/confluence/backups/ 下生成备份包,其中包括文档,附件,用户 还原: ...
- Spring Boot教程(二十五)返回JSON格式
在上述例子中,通过@ControllerAdvice统一定义不同Exception映射到不同错误处理页面.而当我们要实现RESTful API时,返回的错误是JSON格式的数据,而不是HTML页面,这 ...
- 完美解决前端跨域之 easyXDM 的使用和解析
前端跨域问题在大型网站中是比较常见的问题.本文详细介绍了利用 easyXDM 解决前端跨域的原理细节和使用细节,具体使用时可以在文中代码实例的基础上扩展完成. 0.背景 因个别网络运营商存在 HTTP ...