二者使用結果相同,我們寫個代碼分別打印二者返回結果,發現兩個方法獲取的是同一個對象。
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,還是一樣的配方。。。