android 系统资源的加载和获取

文章出处:https://blog.csdn.net/shift_wwx/article/details/39502463


之前的博文android资源访问机制中介绍了android中resources的访问机制,这一篇主要是介绍resources的加载,以及获取。


先来看一下ZygoteInit.java中main函数:

    public static void main(String argv[]) {  
        try {  
            // Start profiling the zygote initialization.  
            SamplingProfilerIntegration.start();  
      
            registerZygoteSocket();  
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,  
                SystemClock.uptimeMillis());  
            if(!SystemProperties.getBoolean("config.enable_quickboot", false)) {  
                preload();  
            }  
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,  
                SystemClock.uptimeMillis());  
      
            // Finish profiling the zygote initialization.  
            SamplingProfilerIntegration.writeZygoteSnapshot();  
      
            // Do an initial gc to clean up after startup  
            gc();  
      
            // Disable tracing so that forked processes do not inherit stale tracing tags from  
            // Zygote.  
            Trace.setTracingEnabled(false);  
      
            // If requested, start system server directly from Zygote  
            if (argv.length != 2) {  
                throw new RuntimeException(argv[0] + USAGE_STRING);  
            }  
      
            if (argv[1].equals("start-system-server")) {  
                startSystemServer();  
            } else if (!argv[1].equals("")) {  
                throw new RuntimeException(argv[0] + USAGE_STRING);  
            }  
      
            Log.i(TAG, "Accepting command socket connections");  
      
            runSelectLoop();  
      
            closeServerSocket();  
        } catch (MethodAndArgsCaller caller) {  
            caller.run();  
        } catch (RuntimeException ex) {  
            Log.e(TAG, "Zygote died with exception", ex);  
            closeServerSocket();  
            throw ex;  
        }  
    }  
其中preload():
    static void preload() {  
        preloadClasses();  
        preloadResources();  
        preloadOpenGL();  
    }  
这里就可以看出,系统资源是在zygote进程启动的时候被加载的,而且资源加载是在startSystemServer();之前。这样就实现了其他应用进程共享系统资源的目标。
private static void preloadResources() {  
    final VMRuntime runtime = VMRuntime.getRuntime();  
  
    Debug.startAllocCounting();  
    try {  
        System.gc();  
        runtime.runFinalizationSync();  
        mResources = Resources.getSystem();  
        mResources.startPreloading();  
        if (PRELOAD_RESOURCES) {  
            Log.i(TAG, "Preloading resources...");  
  
            long startTime = SystemClock.uptimeMillis();  
            TypedArray ar = mResources.obtainTypedArray(  
                    com.android.internal.R.array.preloaded_drawables);  
            int N = preloadDrawables(runtime, ar);  
            ar.recycle();  
            Log.i(TAG, "...preloaded " + N + " resources in "  
                    + (SystemClock.uptimeMillis()-startTime) + "ms.");  
  
            startTime = SystemClock.uptimeMillis();  
            ar = mResources.obtainTypedArray(  
                    com.android.internal.R.array.preloaded_color_state_lists);  
            N = preloadColorStateLists(runtime, ar);  
            ar.recycle();  
            Log.i(TAG, "...preloaded " + N + " resources in "  
                    + (SystemClock.uptimeMillis()-startTime) + "ms.");  
        }  
        mResources.finishPreloading();  
    } catch (RuntimeException e) {  
        Log.w(TAG, "Failure preloading resources", e);  
    } finally {  
        Debug.stopAllocCounting();  
    }  
}

1、Resources.getSystem()

public static Resources getSystem() {  
    synchronized (sSync) {  
        Resources ret = mSystem;  
        if (ret == null) {  
            ret = new Resources();  
            mSystem = ret;  
        }  
  
        return ret;  
    }  
} 
这里mSystem 是static的,我感觉就是单例,其中ret = new Resources();
private Resources() {  
    mAssets = AssetManager.getSystem();  
    // NOTE: Intentionally leaving this uninitialized (all values set  
    // to zero), so that anyone who tries to do something that requires  
    // metrics will get a very wrong value.  
    mConfiguration.setToDefaults();  
    mMetrics.setToDefaults();  
    updateConfiguration(null, null);  
    mAssets.ensureStringBlocks();  
}
其中:
public static AssetManager getSystem() {  
    ensureSystemAssets();  
    return sSystem;  
}   
private static void ensureSystemAssets() {  
    synchronized (sSync) {  
        if (sSystem == null) {  
            AssetManager system = new AssetManager(true);  
            system.makeStringBlocks(false);  
            sSystem = system;  
        }  
    }  
}  
AssetManager的构造函数就跟之前context获取Resources是一样的了。会调用native的addDefaultAssets(),然后添加framework-res.apk路径。

2、preloadDrawables

code中:

TypedArray ar = mResources.obtainTypedArray(  
        com.android.internal.R.array.preloaded_drawables);  
int N = preloadDrawables(runtime, ar);  
ar.recycle(); 
需要加载的是preload_drawables中的所有drawable:
<array name="preloaded_drawables">  
   <item>@drawable/toast_frame</item>  
   <item>@drawable/btn_check_on_pressed_holo_light</item>  
   <item>@drawable/btn_check_on_pressed_holo_dark</item>  
   <item>@drawable/btn_check_on_holo_light</item>  
   <item>@drawable/btn_check_on_holo_dark</item>  
private static int preloadDrawables(VMRuntime runtime, TypedArray ar) {  
    int N = ar.length();  
    for (int i=0; i<N; i++) {  
        if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {  
            if (false) {  
                Log.v(TAG, " GC at " + Debug.getGlobalAllocSize());  
            }  
            System.gc();  
            runtime.runFinalizationSync();  
            Debug.resetGlobalAllocSize();  
        }  
        int id = ar.getResourceId(i, 0);  
        if (false) {  
            Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));  
        }  
        if (id != 0) {  
            if (mResources.getDrawable(id) == null) {  
                throw new IllegalArgumentException(  
                        "Unable to find preloaded drawable resource #0x"  
                        + Integer.toHexString(id)  
                        + " (" + ar.getString(i) + ")");  
            }  
        }  
    }  
    return N;  
} 
通过id传入到函数getDrawable(id):
public Drawable getDrawable(int id) throws NotFoundException {  
    TypedValue value;  
    synchronized (mAccessLock) {  
        value = mTmpValue;  
        if (value == null) {  
            value = new TypedValue();  
        } else {  
            mTmpValue = null;  
        }  
        getValue(id, value, true);  
    }  
    Drawable res = loadDrawable(value, id);  
    synchronized (mAccessLock) {  
        if (mTmpValue == null) {  
            mTmpValue = value;  
        }  
    }  
    return res;  
}
其中loadDrawable实现了装载。

3、preloadColorStateLists
ar = mResources.obtainTypedArray(  
        com.android.internal.R.array.preloaded_color_state_lists);  
N = preloadColorStateLists(runtime, ar); 
需要加载preloaded_color_state_lists:
<array name="preloaded_color_state_lists">  
    <item>@color/primary_text_dark</item>  
    <item>@color/primary_text_dark_disable_only</item>  
    <item>@color/primary_text_dark_nodisable</item>  
    <item>@color/primary_text_disable_only_holo_dark</item> 
private static int preloadColorStateLists(VMRuntime runtime, TypedArray ar) {  
    int N = ar.length();  
    for (int i=0; i<N; i++) {  
        if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {  
            if (false) {  
                Log.v(TAG, " GC at " + Debug.getGlobalAllocSize());  
            }  
            System.gc();  
            runtime.runFinalizationSync();  
            Debug.resetGlobalAllocSize();  
        }  
        int id = ar.getResourceId(i, 0);  
        if (false) {  
            Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));  
        }  
        if (id != 0) {  
            if (mResources.getColorStateList(id) == null) {  
                throw new IllegalArgumentException(  
                        "Unable to find preloaded color resource #0x"  
                        + Integer.toHexString(id)  
                        + " (" + ar.getString(i) + ")");  
            }  
        }  
    }  
    return N;  
}
同样是通过id传入到函数getColorStateList(id):
public ColorStateList getColorStateList(int id) throws NotFoundException {  
    TypedValue value;  
    synchronized (mAccessLock) {  
        value = mTmpValue;  
        if (value == null) {  
            value = new TypedValue();  
        } else {  
            mTmpValue = null;  
        }  
        getValue(id, value, true);  
    }  
    ColorStateList res = loadColorStateList(value, id);  
    synchronized (mAccessLock) {  
        if (mTmpValue == null) {  
            mTmpValue = value;  
        }  
    }  
    return res;  
}
其中loadColorStateList实现了装载。

4、startPreloading 和 finishPreloading

在startPreloading的时候mPreloading会被置true,在finishPreloading的时候将mPreloading置为false

这个mPreloading在loadDrawable等地方起到很关键的作用。

例如loadDrawable:

if (cs != null) {  
    if (mPreloading) {  
        final int changingConfigs = cs.getChangingConfigurations();  
        if (isColorDrawable) {  
            if (verifyPreloadConfig(changingConfigs, 0, value.resourceId,  
                    "drawable")) {  
                sPreloadedColorDrawables.put(key, cs);  
            }  
        } else {  
            if (verifyPreloadConfig(changingConfigs,  
                    LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {  
                if ((changingConfigs&LAYOUT_DIR_CONFIG) == 0) {  
                    // If this resource does not vary based on layout direction,  
                    // we can put it in all of the preload maps.  
                    sPreloadedDrawables[0].put(key, cs);  
                    sPreloadedDrawables[1].put(key, cs);  
                } else {  
                    // Otherwise, only in the layout dir we loaded it for.  
                    final LongSparseArray<Drawable.ConstantState> preloads  
                            = sPreloadedDrawables[mConfiguration.getLayoutDirection()];  
                    preloads.put(key, cs);  
                }  
            }  
        }  
    } else {  
        synchronized (mAccessLock) {  
            //Log.i(TAG, "Saving cached drawable @ #" +  
            //        Integer.toHexString(key.intValue())  
            //        + " in " + this + ": " + cs);  
            if (isColorDrawable) {  
                mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));  
            } else {  
                mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));  
            }  
        }  
    }  
}
会将drawable存放到不同的地方。这样也可以区别zygote进程和普通进程,因为mPreloading只有在zygote进程才会被修改。


结尾:终于小结完了,其中还有很多地方没有细细注释,还是需要实践中掌握。

至于Resources的详解,我想以后也需要多小结的,详细的说说Resources中的资源分配、资源文件的利用,并在这里记录:

android资源文件之:shape详解











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

私房菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值