基于ActivityThread 中一些常用的知識點記錄
的拓展涨醋,分析一下通過 ActivityThread 獲取 applicationInfo 對象的差異赦肋。
applicationInfo 包含當前應(yīng)用的大部分信息癌蚁,因此是個很重要的部分
1. ActivityThread.currentApplication().getApplicationInfo()
獲取到應(yīng)用進程的loadedApk對象的 applicationInfo
Application -> ContextWrapper -> ContextImpl 成員變量 mLoadedApk.getApplicationInfo
2. ActivityThread.currentApplication().getBaseContext().createPackageContextAsUser(packageName, 0, new UserHandle(userId)).getApplicationInfo()
獲取到緩存的loadedApk的 applicationInfo
a.先獲取context (根據(jù)activityThread / loadedApp 新建一個)
Application -> ContextWrapper.getBaseContext -> ContextImpl.createPackageContextAsUser()
這時會通過 ActivityThread.getPackageInfo() 查找緩存中的loadedApp, 然后再創(chuàng)建 ContextImpl
b.在獲取applicationInfo 對象
3. 總結(jié):
(1) (2) 最終都是通過 ContextImpl.getApplicationInfo(), 差異就在于他們可能是不同的對象,
導致 mPackageInfo 即 loadedApp 對象是不一樣的, 例如前者是 應(yīng)用進程 最新的匾竿, 而后者 是 ActivityThread緩存中的(mResourcePackages)
//ContextImpl.java
class ContextImpl extends Context {
@UnsupportedAppUsage
final @NonNull LoadedApk mPackageInfo;
@Override
public ApplicationInfo getApplicationInfo() {
if (mPackageInfo != null) {
return mPackageInfo.getApplicationInfo();
}
throw new RuntimeException("Not supported in system context");
}
}
// LoadedApk.java
public final class LoadedApk {
@UnsupportedAppUsage
private ApplicationInfo mApplicationInfo;
@UnsupportedAppUsage
public ApplicationInfo getApplicationInfo() {
return mApplicationInfo;
}
}
注意:
(1) ActivityThread.currentApplication().getBaseContext() 確保的是當前進程調(diào)用的俐镐,即userId 一致.
(2) context.createApplicationContext(mApplication,Context.CONTEXT_RESTRICTED)
這里的 context 不一定的是和mApplication(applicationInfo) 同一個userId的秒梳, 所以可能導致無法從 ActivityThread的緩存中取LoadedApk的對象