Android是如何根据限定符,来寻找合适的资源文件的?

转载自:http://blog.csdn.net/zhaokaiqiang1992

本文主要介绍了当我们使用限定符修饰我们的资源文件夹,例如drawable-en-ldpi时,Android系统是根据什么规则对这些文件夹进行筛选和选择的。

本文不是严肃翻译,想查看原文的请戳 Providing Resources

我们都知道,当我们使用限定符修饰资源文件夹,比如说drawable或者是values的时候,Android系统会根据运行时所在的设备属性和 配置,来动态的选择最合适的资源文件,那么,这个过程具体是如何进行的呢?我们下面就以drawable文件夹为例,详细的介绍这个选择的过程和注意事 项。

现在我们要假设这样一种情况,我们在下面这些文件夹里面都包含同一张图片的不同版本:

  • drawable/

  • drawable-en/

  • drawable-fr-rCA/

  • drawable-en-port/

  • drawable-en-notouch-12key/

  • drawable-port-ldpi/

  • drawable-port-notouch-12key/

并且假设我们的运行时设备配置如下:

  • Locale = en-GB

  • Screen orientation = port

  • Screen pixel density = hdpi

  • Touchscreen type = notouch

  • Primary text input method = 12key

通过比较设备配置和上面这些可用的限定符修饰的这些drawable文件夹,最终Android设备选择了来自drawable-en-port文件夹的的图片。

系统是根据下面的逻辑来判断为什么要选择这个文件夹里面的图片的:

76b4cd8e0de05866.png

翻译版本:

1.排除和设备配置相矛盾的限定符2.按照限定符表的优先级选择下一个限定符3.是否有资源文件夹使用了这个限定符?4.排除不包含这个限定符的文件夹(应该还有一个到第2步的回环,画不出来)yesno

  1. 首先排除和设备配置想矛盾的drawable文件夹。因为drawable-fr-rCA/这个文件夹和语言环境en-GB相矛盾,所以直接就被排除掉了。现在我们的资源文件夹情况如下:
  • drawable/

  • drawable-en/

  • drawable-fr-rCA/

  • drawable-en-port/

  • drawable-en-notouch-12key/

  • drawable-port-ldpi/

  • drawable-port-notouch-12key/

**注意:**屏幕的像素密度修饰符,不会因为与设备配置不一样而被排除掉,即使我们的设备现在是hdpi,但是drawable-port-ldpi/也不会因为限定符的原因被排除,因为在这个阶段,所有的屏幕密度都被考虑进行适配。更多信息请参考Support Multiple Screen
2.  按照表格中的顺序,选择下一个高优先级的修饰限定符。(从MCC开始,一直往下)

限定符的顺序如下所示,从上到下,优先级递减。因为好多很少用到,所以这是一部分,更加详细的请参考原文。

配置限定符取值示例
MCC MNCmcc310
语言en-rUS
布局方向ldrtl ldltr
最小宽度限定符sw320dp
可获得宽度w720dp
可获得高度h720dp
屏幕尺寸large
屏幕方面long notlong
屏幕方向port land
UI模式car appliance watch
夜晚模式night notnight
屏幕像素密度mdpi nodpi
触摸屏幕类型notouch finger

3. 有没有文件夹包含这些限定符?
- 如果是NO,就返回第二步,然后看下一个限定符。(在这个例子里面,在找到语言限定符之前回答都是NO)
- 如果是YES,继续第四步。  
4. 排除不包含这个限定符的资源文件夹。在这个例子里面,系统会排除所有不包含语言限定符的资源文件夹。

  • drawable/

  • drawable-en/

  • drawable-en-port/

  • drawable-en-notouch-12key/

  • drawable-port-ldpi/

  • drawable-port-notouch-12key/

**警告:**如果上面提到的限定符是屏幕密度,那么系统就会选择最接近设备屏幕密度的资源文件夹。通常来说,Android更倾向于缩小一个比较大的图片而不是放大一个比较小的图片。
5.  返回上去,并且重复2,3,4步,一直到只有一个文件夹剩下。在这个示例中,屏幕方向是下一个限定符,所以说,不指定屏幕方向限定符的文件夹就被排除了。

  • drawable-en/

  • drawable-en-port/

  • drawable-en-notouch-12key/

现在就剩下我们的文件夹drawable-en-port/了。

虽然在我们请求每个资源文件的时候,这个步骤都会执行,但是系统对一些方面进行了优化。一旦我们的设备配置已知,那么那些永远不可能匹配的文件夹就 会被排除出去。举例来说,如果我们的语言配置是英语,那么有其他语言限定符的资源文件夹就被系统排除出去,不再进行检查,这样就可以提高我们的性能。当 然,那么没有指定语言限定符的资源文件夹还是存在的。

当我们选择一个基于屏幕尺寸的限定度的时候,如果没有非常适合的资源文件夹,那么系统就会选择比当前屏幕小的资源文件夹。举例来说,如果我们没有为 large屏幕配置合适的资源文件,那么系统就会选择normal屏幕大小的资源。然而,如果当前可选的资源文件夹的屏幕尺寸修饰限定符比现在的屏幕大, 那么我们的系统不会使用这些资源,而是会直接崩溃。举例来说,如果我们的布局资源只有xlarge限定符,如果我们在normal-size设备运行,就 会直接崩溃。

**注意:**前面的限定符的优先级顺序比限定符的数量更加重要。举例来说,在第四部之前,可选的资源文件夹里面 drawable-port-notouch-12key可能有三个限定符符合现在的设备,而drawable-en只有一个限定符符合,但是因为语言限 定符的优先级比较高,所以drawable-port-notouch-12key文件夹就直接被排除了。