文章出处:http://blog.csdn.net/shift_wwx


之前的博文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详解











更多相关文章

  1. Android模拟键盘和键盘监听的一些调研
  2. Android(安卓)framework源码按键操作的完整流程
  3. Android(安卓)中文API (91) ―― GestureDetector
  4. Jsoup使用教程(一)
  5. android 进程内存查看
  6. 转 : Android中Message机制的灵活应用
  7. Android启动过程
  8. 创建SqliteDatabase
  9. 箭头函数的基础使用

随机推荐

  1. Android(安卓)EditText example
  2. Android(安卓)照相机打开方法
  3. Android(安卓)监听wifi广播的两种方式
  4. 如何使用SharedPerferences
  5. android之【事件监听器】
  6. Android(安卓)获取无线蓝牙MAC信息代码
  7. Android: Sensors on Android(安卓)2.3 -
  8. Android(安卓)4.4.3应用,高通平台 去掉应
  9. android 对象保存到SP
  10. Android布局学习之――按钮居中