当前位置:网站首页>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
边栏推荐
- GBase 8c系统表-pg_collation
- Gbase 8C trigger (I)
- Gbase 8C system table PG_ amop
- Deep Reinforcement Learning for Intelligent Transportation Systems: A Survey 论文阅读笔记
- Gbase 8C function / stored procedure parameters (II)
- easyExcel
- HW-初始准备
- Tongda OA V12 process center
- Random shuffle note
- 2022-2028 global splicing display industry research and trend analysis report
猜你喜欢
![[shutter] bottom navigation bar page frame (bottomnavigationbar bottom navigation bar | pageview sliding page | bottom navigation and sliding page associated operation)](/img/6e/67bc187a89fb9125856c78c89f7bfb.gif)
[shutter] bottom navigation bar page frame (bottomnavigationbar bottom navigation bar | pageview sliding page | bottom navigation and sliding page associated operation)
![[fluent] listview list (map method description of list set | vertical list | horizontal list | code example)](/img/e5/c01f760b07b495f5b048ea367e0c21.gif)
[fluent] listview list (map method description of list set | vertical list | horizontal list | code example)

Today, it's time to copy the bottom!

Linear rectification function relu and its variants in deep learning activation function

How to change the panet layer in yolov5 to bifpn

awk从入门到入土(0)awk概述

Summary of interview project technology stack

Kubernetes family container housekeeper pod online Q & A?
![[principles of multithreading and high concurrency: 1_cpu multi-level cache model]](/img/7e/ad9ea78868126b149bd9f15f587e6c.jpg)
[principles of multithreading and high concurrency: 1_cpu multi-level cache model]

Practice of traffic recording and playback in vivo
随机推荐
Create + register sub apps_ Define routes, global routes and sub routes
GBase 8c触发器(三)
GBase 8c系统表-pg_constraint
Tongda OA V12 process center
[Hcia]No.15 Vlan间通信
GBase 8c系统表pg_database
A2L file parsing based on CAN bus (2)
GBase 8c系统表-pg_auth_members
搭建私有云盘 cloudreve
HTB-Devel
Counter统计数量后,如何返回有序的key
As a leader, how to control the code version and demand development when the epidemic comes| Community essay solicitation
Gbase 8C trigger (I)
Compréhension simple de SVG
GBase 8c系统表pg_cast
My creation anniversary
sql server数据库添加 mdf数据库文件,遇到的报错
Restcloud ETL cross database data aggregation operation
Gbase 8C system table PG_ collation
[shutter] bottom navigation bar page frame (bottomnavigationbar bottom navigation bar | pageview sliding page | bottom navigation and sliding page associated operation)