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; } }
相关阅读
Android getResources().getColor() 过时 替代方法
在Java代码中设置控件的Color时,用getResources().getColor()出现如下提示: getColor方法在Android 6.0即API 23中 已经过时,替代方