当前位置:网站首页>Source code analysis | resource loading resources
Source code analysis | resource loading resources
2022-07-03 02:41:00 【Nuggets】
Understand the loading process of resources , Realize loading the resource file in the skin file
Resource loading
imageView In the layout src How is the picture loaded ?
mResources.loadDrawable(value, value.resourceId, density, mTheme)
It's all through Resource Loading
Since resources are loaded through Resource class , If you want to get another apk Resource files in , Then instantiate one by yourself Resource Can I load it ?
- The first thing to know is that Resource How to instantiate
@Override
public Resources getResources() {
if (mResources == null && VectorEnabledTintResources.shouldBeUsed()) {
mResources = new VectorEnabledTintResources(this, super.getResources());
}
return mResources == null ? super.getResources() : mResources;
} stay AppcompatActivity in , There is one getResources Method to get Resource. If mResource by null, Then what is called is super.Resources().
@Override
public Resources getResources() {
return getResourcesInternal();
}
private Resources getResourcesInternal() {
if (mResources == null) {
if (mOverrideConfiguration == null) {
//1
mResources = super.getResources();
} else {
final Context resContext = createConfigurationContext(mOverrideConfiguration);
//2
mResources = resContext.getResources();
}
}
return mResources;
}above 1 and 2 In the end, what is called is Context Of getResource Method , however Context Of getResource It's an abstract method , We have to find his implementation class .
// Returns the... Of the application package Resources example public abstract Resources getResources();
His implementation class is actually ContextImpl , This class is in the as You can't see it above , You need to check from the source code
@Override
public Resources getResources() {
return mResources;
}Finally, the above method is called , as for mResource How to instantiate , as follows :
private static Resources createResources(IBinder activityToken, LoadedApk pi, String splitName,
int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
final String[] splitResDirs;
final ClassLoader classLoader;
try {
splitResDirs = pi.getSplitPaths(splitName);
classLoader = pi.getSplitClassLoader(splitName);
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
return ResourcesManager.getInstance().getResources(activityToken,
pi.getResDir(),
splitResDirs,
pi.getOverlayDirs(),
pi.getApplicationInfo().sharedLibraryFiles,
displayId,
overrideConfig,
compatInfo,
classLoader);
}establish Resource Will go to createResources Method .
You can see that the final call is ResourcesManager Of getResource Method ,
public @Nullable 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);
}
}among Parameters resDir Namely apk Storage path . In this way Parameters are integrated into ResourceKey in , And then it calls getOrCreateResources Method
private @Nullable Resources getOrCreateResources(@Nullable IBinder activityToken,
@NonNull ResourcesKey key, @NonNull ClassLoader classLoader) {
ynchronized (this) {
// From the cache ResourcesImpl
ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(key);
if (resourcesImpl != null) {
if (DEBUG) {
Slog.d(TAG, "- using existing impl=" + resourcesImpl);
}
//1
return getOrCreateResourcesForActivityLocked(activityToken, classLoader,
resourcesImpl, key.mCompatInfo);
}
} 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);
}
//2
return getOrCreateResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo);
}
// We will create the ResourcesImpl object outside of holding this lock.
}
// If not, create
ResourcesImpl resourcesImpl = createResourcesImpl(key);
if (resourcesImpl == null) {
return null;
}
// Join the cache
mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
final Resources resources;
if (activityToken != null) {
//3
resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader,
resourcesImpl, key.mCompatInfo);
} else {
//4
resources = getOrCreateResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo);
}
return resources;
}
}
Look for the mark Of 1,2,3,4 , These four locations call two methods , These two methods will eventually be created through the following sentence Resource
// Create a new resource reference and use the existing ResourcesImpl object
Resources resources = compatInfo.needsCompatResources() ? new CompatResources(classLoader)
: new Resources(classLoader);
resources.setImpl(impl);Come here Resources It was created successfully
We just need to know Resource Just how to instantiate , What is it? new Coming out .
- Resources Constructor for
@Deprecated
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
this(null);
mResourcesImpl = new ResourcesImpl(assets, metrics, config, new DisplayAdjustments());
}
@UnsupportedAppUsage
public Resources(@Nullable ClassLoader classLoader) {
mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
}Resources Construction method , Because of the source code Different versions ,new Resource The structure may also be different . It looks a little different , But it's almost , stay new Resources Next line , Called setImpl Method , Incoming ResourcesImpl Actually by createResourcesImpl Method :
private @Nullable ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) {
final DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration);
daj.setCompatibilityInfo(key.mCompatInfo);
final AssetManager assets = createAssetManager(key);
//.....
final DisplayMetrics dm = getDisplayMetrics(key.mDisplayId, daj);
final Configuration config = generateConfig(key, dm);
final ResourcesImpl impl = new ResourcesImpl(assets, dm, config, daj);
return impl;
}Through the top Method to create ResourceImpl, In fact, it is similar to that created in the first construction method .
- ResourceImpl
structure :new ResourcesImpl(assets, dm, config, daj);
- assets: AssetManager Resource management , Create as follows , adopt Builder establish AssetManager object , And passed in various paths , In some versions of the source code AssetManager It's direct new Coming out , And called addAssetPath Methods the incoming apk route
protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) {
final AssetManager.Builder builder = new AssetManager.Builder();
// resDir can be null if the 'android' package is creating a new Resources object.
// This is fine, since each AssetManager automatically loads the 'android' package
// already.
if (key.mResDir != null) {
//mResDir:apk The catalog of
builder.addApkAssets(loadApkAssets(key.mResDir, false /*sharedLib*/, false /*overlay*/));
}
if (key.mSplitResDirs != null) {
for (final String splitResDir : key.mSplitResDirs) {
builder.addApkAssets(loadApkAssets(splitResDir, false /*sharedLib*/,
false /*overlay*/));
}
}
if (key.mOverlayDirs != null) {
for (final String idmapPath : key.mOverlayDirs) {
builder.addApkAssets(loadApkAssets(idmapPath, false /*sharedLib*/,
true /*overlay*/));
}
}
if (key.mLibDirs != null) {
for (final String libDir : key.mLibDirs) {
if (libDir.endsWith(".apk")) {
builder.addApkAssets(loadApkAssets(libDir, true /*sharedLib*/,
false /*overlay*/));
}
}
}
return builder.build();
}Resource loading summary : All resources are loaded through Resource ,Resource -> When building objects of new The object of ,-> There is a very important parameter AssetManager, This class is time Resource Core examples .
And finally through AssetManager obtain .
Create by yourself Resources Load the resource file in the skin file
1, Understand skin files
Skin file is actually a apk, Add resource files to the project , Then generate a apk, Then this apk Is the skin file , The resources in the skin file must be consistent with those in the project .
2, adopt Resources Get the resource file in the skin file , And load
val superRes = resources
// Create reflection AssetManager, Construction is hidden , You can't create
val assetManager = AssetManager::class.java.newInstance()
// Reflection method , Add locally downloaded resources apk Catalog ,apk The suffix of can be changed at will , This is changed to .skin
val method =
AssetManager::class.java.getDeclaredMethod("addAssetPath", String::class.java)
method.invoke(
assetManager, "${Environment.getExternalStorageDirectory().absolutePath}${File.separator}red.skin"
)
// Create a Resource, The specific methods are in the source code , We've already talked about that .
// The parameters created are all in the source code , Just copy it
val resources = Resources(assetManager, superRes.displayMetrics, superRes.configuration)
//1, Resource name , The resource type , Package name
val drawableId = resources.getIdentifier("image_src", "drawable", "com.qs.redskin")
// obtain resources
val drawable = resources.getDrawable(drawableId)
mImageView.setImageDrawable(drawable)Through the above steps, you can load In the skin The resource file has . Be careful to apply for Storage rights
The above is just a simple Demo
边栏推荐
- [fluent] listview list (map method description of list set | vertical list | horizontal list | code example)
- Xiaodi notes
- ASP. Net core 6 framework unveiling example demonstration [02]: application development based on routing, MVC and grpc
- 【翻译】Flux安全。通过模糊处理获得更多信心
- SQL Server Query spécifie la structure de la table
- JS的装箱和拆箱
- The left value and the right finger explain better
- GBase 8c系统表-pg_am
- 簡單理解svg
- GBase 8c系统表pg_database
猜你喜欢

HTB-Devel

Mathematical statistics -- Sampling and sampling distribution

Create + register sub apps_ Define routes, global routes and sub routes

Oauth2.0 authentication, login and access "/oauth/token", how to get the value of request header authorization (basictoken)???

Build a private cloud disk cloudrev

SqlServer行转列PIVOT

The data in servlet is transferred to JSP page, and the problem cannot be displayed using El expression ${}

UDP receive queue and multiple initialization test

Tongda OA homepage portal workbench

HTB-Devel
随机推荐
Add automatic model generation function to hade
Interview stereotyped version
Strategy application of Dameng database
[Hcia]No.15 Vlan间通信
Gbase 8C trigger (I)
The Linux server needs to install the agent software EPS (agent) database
GBase 8c系统表pg_cast
【翻译】后台项目加入了CNCF孵化器
Gbase 8C create user / role example 2
C语言中左值和右值的区别
ASP. Net core 6 framework unveiling example demonstration [02]: application development based on routing, MVC and grpc
Kubernetes family container housekeeper pod online Q & A?
Word word word
sql server 查詢指定錶的錶結構
GBase 8c 触发器(一)
【翻译】Flux安全。通过模糊处理获得更多信心
[tutorial] chrome turns off cross domain policies CORS and samesite, and brings cookies across domains
HTB-Devel
where 1=1 是什么意思
MUX VLAN Foundation