二者使用结果相同,我们写个代码分别打印二者返回结果,发现两个方法获取的是同一个对象。
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,还是一样的配方。。。