getResources()详解


/**
 * Return <code>getActivity().getResources()</code>.
 */
final public Resources getResources() {
    if (mHost == null) {
        throw new IllegalStateException("Fragment " + this + " not attached to Activity");
    }
    return mHost.getContext().getResources();
}
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
    public HostCallbacks() {
        super(FragmentActivity.this /*fragmentActivity*/);
    }
}

mHost 是 FragmentHostCallback() 是在FragmentActivity 时候初始化的传给FragmentHostCallback() 并执行四个参数的构造方法 分别给mActivity 赋值,将mActivity强转 mContext并赋值mContext,获取mActivity的mHandler并赋值给mHandler,第四个参数是0。mHost的 getContext()就是调用Activity的mContext。getResources就是调用Activity的 getResources

public abstract class Context {
       public abstract Resources getResources();
}

我之前文章说过 Context 的具体实现类是ContextImpl,我们看下ContextImpl 的getResources是怎么实现的,

@Override
public Resources getResources() {
    return mResources;
}

直接返回一个mResources ,在看下mResources是哪里赋值的

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

    mMainThread = mainThread;
    mActivityToken = activityToken;
    mFlags = flags;

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

    mPackageInfo = packageInfo;
    mResourcesManager = ResourcesManager.getInstance();
   // 获取 resources
    Resources resources = packageInfo.getResources(mainThread);
    // mResources 赋值
    mResources = resources;

    mDisplay = (createDisplayWithId == Display.INVALID_DISPLAY) ? display
            : mResourcesManager.getAdjustedDisplay(displayId,      mResources.getDisplayAdjustments());

 
}

我之前文章也讲过,ContextImpl创建是在 ActivityThread 创建时调用getSystemContext方法进行创建的

public ContextImpl getSystemContext() {
    synchronized (this) {
        if (mSystemContext == null) {
            mSystemContext = ContextImpl.createSystemContext(this);
        }
        return mSystemContext;
    }
}
static ContextImpl createSystemContext(ActivityThread mainThread) {
    创建LoadedApk
    LoadedApk packageInfo = new LoadedApk(mainThread);
    创建ContextImpl
    ContextImpl context = new ContextImpl(null, mainThread,
            packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
    context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
            context.mResourcesManager.getDisplayMetrics());
    return context;
}

我们在回到getResources方法 ,上面看到 packageInfo.getResources(mainThread); packageInfo就是LoadedApk这里在看下LoadedApk的getResources是如何实现的

public Resources getResources(ActivityThread mainThread) {
    if (mResources == null) {
        mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
                mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
    }
    return mResources;
}

mResources 是通过 ActivityThread的getTopLevelResources方法获取的

Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
        String[] libDirs, int displayId, LoadedApk pkgInfo) {
    return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
            displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader());
}

这里是 mResourcesManager 的getResources方法

public @NonNull Resources getResources(@Nullable IBinder activityToken,
        @Nullable String resDir,
        @Nullable String[] splitResDirs,
        @Nullable String[] overlayDirs,
        @Nullable String[] libDirs,
        int displayId,
        @Nullable Configuration overrideConfig,
        @NonNull CompatibilityInfo compatInfo,
        @Nullable ClassLoader classLoader) {
    try {
        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#getResources");
        final ResourcesKey key = new ResourcesKey(
                resDir,
                splitResDirs,
                overlayDirs,
                libDirs,
                displayId,
                overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
                compatInfo);
        classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
        return getOrCreateResources(activityToken, key, classLoader);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
    }
}
private @NonNull Resources getOrCreateResources(@Nullable IBinder activityToken,
        @NonNull ResourcesKey key, @NonNull ClassLoader classLoader) {
    synchronized (this) {
        if (DEBUG) {
            Throwable here = new Throwable();
            here.fillInStackTrace();
            Slog.w(TAG, "!! Get resources for activity=" + activityToken + " key=" + key, here);
        }

        if (activityToken != null) {
            final ActivityResources activityResources =
                    getOrCreateActivityResourcesStructLocked(activityToken);

            // Clean up any dead references so they don't pile up.
            ArrayUtils.unstableRemoveIf(activityResources.activityResources,
                    sEmptyReferencePredicate);

            // Rebase the key's override config on top of the Activity's base override.
            if (key.hasOverrideConfiguration()
                    && !activityResources.overrideConfig.equals(Configuration.EMPTY)) {
                final Configuration temp = new Configuration(activityResources.overrideConfig);
                temp.updateFrom(key.mOverrideConfiguration);
                key.mOverrideConfiguration.setTo(temp);
            }

            ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(key);
            if (resourcesImpl != null) {
                if (DEBUG) {
                    Slog.d(TAG, "- using existing impl=" + resourcesImpl);
                }
                return getOrCreateResourcesForActivityLocked(activityToken, classLoader,
                        resourcesImpl);
            }

            // We will create the ResourcesImpl object outside of holding this lock.

        } else {
            // Clean up any dead references so they don't pile up.
            ArrayUtils.unstableRemoveIf(mResourceReferences, sEmptyReferencePredicate);

            // Not tied to an Activity, find a shared Resources that has the right ResourcesImpl
            ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(key);
            if (resourcesImpl != null) {
                if (DEBUG) {
                    Slog.d(TAG, "- using existing impl=" + resourcesImpl);
                }
                return getOrCreateResourcesLocked(classLoader, resourcesImpl);
            }

            // We will create the ResourcesImpl object outside of holding this lock.
        }
    }

    // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
    ResourcesImpl resourcesImpl = createResourcesImpl(key);

    synchronized (this) {
        ResourcesImpl existingResourcesImpl = findResourcesImplForKeyLocked(key);
        if (existingResourcesImpl != null) {
            if (DEBUG) {
                Slog.d(TAG, "- got beat! existing impl=" + existingResourcesImpl
                        + " new impl=" + resourcesImpl);
            }
            resourcesImpl.getAssets().close();
            resourcesImpl = existingResourcesImpl;
        } else {
            // Add this ResourcesImpl to the cache.
            mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
        }

        final Resources resources;
        if (activityToken != null) {
            resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader,
                    resourcesImpl);
        } else {
            resources = getOrCreateResourcesLocked(classLoader, resourcesImpl);
        }
        return resources;
    }
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值