Android中的Resources解析

下面我们从Application的创建说起

/frameworks/base/core/java/android/app/ActivityThread.java

private void handleBindApplication(AppBindData data) {
    // 1.1 获取应用信息LoadedApk
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    // 1.2、创建Application的Context
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    // ......
}
一、获取应用信息LoadedApk
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
        CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
        ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
        boolean registerPackage) {
    synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
        // 这里就可以看到,LoadedApk会缓存在mPackages中,如果为null,就会创建一个,之后就不需要创建了
        if (includeCode) {
            ref = mPackages.get(aInfo.packageName);
        } else {
            ref = mResourcePackages.get(aInfo.packageName);
        }
        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            packageInfo =
                new LoadedApk(this, aInfo, compatInfo, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

            if (mSystemThread && "android".equals(aInfo.packageName)) {
                packageInfo.installSystemApplicationInfo(aInfo,
                        getSystemContext().mPackageInfo.getClassLoader());
            }

            if (includeCode) {
                mPackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            } else {
                mResourcePackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            }
        }
        return packageInfo;
    }
}
二、创建Application的Context
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    // 直接创建一个ContextImpl对象
    return new ContextImpl(null, mainThread,
            packageInfo, null, null, false, null, null);
}

/frameworks/base/core/java/android/app/ContextImpl.java

private ContextImpl(ContextImpl container, ActivityThread mainThread,
        LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
        Display display, Configuration overrideConfiguration) {
    mOuterContext = this;

    mMainThread = mainThread;
    mActivityToken = activityToken;
    mRestricted = restricted;

    if (user == null) {
        user = Process.myUserHandle();
    }
    mUser = user;

    mPackageInfo = packageInfo;
    mResourcesManager = ResourcesManager.getInstance();
    mDisplay = display;
    mOverrideConfiguration = overrideConfiguration;

    final int displayId = getDisplayId();
    CompatibilityInfo compatInfo = null;
    if (container != null) {
        compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();
    }
    if (compatInfo == null && displayId == Display.DEFAULT_DISPLAY) {
        compatInfo = packageInfo.getCompatibilityInfo();
    }
    mDisplayAdjustments.setCompatibilityInfo(compatInfo);
    mDisplayAdjustments.setActivityToken(activityToken);
    //packageInfo为LoadedApk对象,也就是这里调用了LoadedApk的getResources方法
    Resources resources = packageInfo.getResources(mainThread);
    if (resources != null) {
        if (activityToken != null
                || displayId != Display.DEFAULT_DISPLAY
                || overrideConfiguration != null
                || (compatInfo != null && compatInfo.applicationScale
                        != resources.getCompatibilityInfo().applicationScale)) {
            resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
                    packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
                    packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
                    overrideConfiguration, compatInfo, activityToken);
        }
    }
    mResources = resources;

    if (container != null) {
        mBasePackageName = container.mBasePackageName;
        mOpPackageName = container.mOpPackageName;
    } else {
        mBasePackageName = packageInfo.mPackageName;
        ApplicationInfo ainfo = packageInfo.getApplicationInfo();
        if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
            // Special case: system components allow themselves to be loaded in to other
            // processes.  For purposes of app ops, we must then consider the context as
            // belonging to the package of this process, not the system itself, otherwise
            // the package+uid verifications in app ops will fail.
            mOpPackageName = ActivityThread.currentPackageName();
        } else {
            mOpPackageName = mBasePackageName;
        }
    }

    mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}

/frameworks/base/core/java/android/app/LoadedApk.java

public Resources getResources(ActivityThread mainThread) {
    if (mResources == null) {
        // 可以看到直接调用的是ActivityThread的getTopLevelResources方法
        mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
                mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
    }
    return mResources;
}

/frameworks/base/core/java/android/app/ActivityThread.java

Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
        String[] libDirs, int displayId, Configuration overrideConfiguration,
        LoadedApk pkgInfo) {
    // 可以看到直接调用的是ResourcesManager的getTopLevelResources方法
    return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
            displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
}
ActivityThread() {
    mResourcesManager = ResourcesManager.getInstance();
}

/frameworks/base/core/java/android/app/ResourcesManager.java

// ResourcesManager是一个单例类,也就是说只会有一份,所以我们所有资源的获取最终调用的都是这个对象
public static ResourcesManager getInstance() {
    synchronized (ResourcesManager.class) {
        if (sResourcesManager == null) {
            sResourcesManager = new ResourcesManager();
        }
        return sResourcesManager;
    }
}

欢迎关注微信公众号:DroidMind
精品内容独家发布平台


呈现与博客不一样的技术干货

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值