基于ActivityThread 中一些常用的知识点记录
的拓展,分析一下通过 ActivityThread 获取 applicationInfo 对象的差异。
applicationInfo 包含当前应用的大部分信息,因此是个很重要的部分
1. ActivityThread.currentApplication().getApplicationInfo()
获取到应用进程的loadedApk对象的 applicationInfo
Application -> ContextWrapper -> ContextImpl 成员变量 mLoadedApk.getApplicationInfo
2. ActivityThread.currentApplication().getBaseContext().createPackageContextAsUser(packageName, 0, new UserHandle(userId)).getApplicationInfo()
获取到缓存的loadedApk的 applicationInfo
a.先获取context (根据activityThread / loadedApp 新建一个)
Application -> ContextWrapper.getBaseContext -> ContextImpl.createPackageContextAsUser()
这时会通过 ActivityThread.getPackageInfo() 查找缓存中的loadedApp, 然后再创建 ContextImpl
b.在获取applicationInfo 对象
3. 总结:
(1) (2) 最终都是通过 ContextImpl.getApplicationInfo(), 差异就在于他们可能是不同的对象,
导致 mPackageInfo 即 loadedApp 对象是不一样的, 例如前者是 应用进程 最新的, 而后者 是 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() 确保的是当前进程调用的,即userId 一致.
(2) context.createApplicationContext(mApplication,Context.CONTEXT_RESTRICTED)
这里的 context 不一定的是和mApplication(applicationInfo) 同一个userId的, 所以可能导致无法从 ActivityThread的缓存中取LoadedApk的对象