java getapplicationcontext_getApplication()和getApplicationContext()区别

二者使用结果相同,我们写个代码分别打印二者返回结果,发现两个方法获取的是同一个对象。

public class MainActivity extendsActivity {

@Overrideprotected voidonCreate(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@3d34e672019-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中:

@OverridepublicContext getApplicationContext() {return (mPackageInfo != null) ?mPackageInfo.getApplication() : mMainThread.getApplication();

}

再来看看getApplication方法(只存在于Activity和Service中):

public finalApplication getApplication() {returnmApplication;

}

那mApplication的赋值在哪?搜索一下,只有一个地方有赋值:

final voidattach(Context context, ActivityThread aThread,

Instrumentation instr, IBinder token,intident,

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() {returnmApplication;

}

在LoadedApk也有一个mApplication,这个mApplication的赋值在LoadedApk的makeApplication:

public Application makeApplication(booleanforceDefaultAppClass,

Instrumentation instrumentation) {

...if (mApplication != null) {returnmApplication;

}

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中:

publicApplication getApplication() {returnmInitialApplication;

}

再来看看mInitialApplication的赋值在哪里:

private voidhandleBindApplication(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 voidattach(Application application) {

mApplication=application;

}

也就是说等于调用attach方法时传入的application,那Activity的attach是在哪里调用呢,我们要来到反复提到的一个应用程序入口类ActivityThread,它有一个performLaunchActivity的方法,用来加载一个Activity,这里就有attach()的调用(我去掉了其他参数):

privateActivity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

...

Application app= r.packageInfo.makeApplication(false, mInstrumentation);

...

activity.attach(app);

...

}

我们发现又来了。。。熟悉的makeApplication(),r.packageInfo果然是LoadedApk类,最后殊途同归,又来到了这个单例,返回程序唯一的mApplication,还是一样的配方。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值