在Android中,做这个事情,变得简单许多,通过预设的一些Xml属性,能够轻松的搞定。如上图所示,是Radio Button的背景。通过搭配不同的属性,就可以自动转换背景。比如第一个<item>,说的是当Radio Button被选中,并且具有焦点的时候,显示btn_radio_on这幅图片,而最后一个<item>,说的是前述条件都不满足,并且处于选中状态,那么显示btn_radio_on这幅图片。
另外一个更易变的因素,就是
手机硬件/软件环境了,毕竟,不是家家都是苹果,一个平台搭一款手机,手机款形多样化,几乎是避免不了的问题。没有人希望自己做的软件在大屏幕手机上闪亮光鲜,换个小屏幕就惨不忍睹,竖屏看像那么回事横屏看就挤做一团。还有就是
语言环境了,做为一个有国际眼光的coder,作面向世界的NB软件是咱的梦想,但我们不能因为自己的梦想逼迫大家都去学中文,做一款软件可以根据手机的语言环境选择最合适展示的语言,很多时候,是一个需要具备的功能点。
在Android中,实现这些,都是举手之劳。方法就是将和环境相关的资源,放入特定名称的文件夹中。比如,表示简体中文字符信息的资源,可以放到
values-zh-rCN中去,当系统语言环境为简体中文时,就会呈现出中文的字符信息。在Android中,很多相关配置项,都可以按照这样的方式参与到资源自适应的活动中来,包括屏幕大小,屏幕朝向,屏幕分辨率,语言环境,触屏类型,SDK版本等等。系统会给所有配置项一个
优先级(或者说权重,次序之类的),当用户提供了多份资源的时候,系统会根据优先级从高到底
淘汰备选资源,如果淘汰仅
剩了一个,那就是最符合当前系统软硬件语言环境的资源项,如果
一个不剩,择启用
默认项(最是形如values这样没有任何尾巴目录中的资源...)。因此,默认的资源是非常重要的,它必须是其他所有可选资源项的
超集,否则在资源选择失败的情况下,应用会凄凉的崩溃。
R类
在使用资源后,界面逻辑与底层逻辑的耦合被降低了,但这不意味着,两者没有关联了。比如,需要为某个按钮增加一个点击事件,就需要定位到所需的那个按钮;再比如,你需要使用某个字符串资源,通知用户某件事情,就需要能定位到资源中放置的该字串。
最显而易见的一种方式,就是通过字符串比较,用
名字信息在资源的xml描述文件中定位到所需的内容,加载并使用。这种方式,解决了查找的问题,但反复的字符串比较,势必带来严重的效率隐患。因此,在Android中,类似于Symbian的方法,引入了一个R类。
它的基本思想是,通过增加一个
额外的编译器,为所有的
资源项,都赋予一个
32位的整形数来表示,同一个资源像的不同配置,都
使用同一个id。这个整形数,就相当于这个资源项的
门牌号码,能够帮助定位到对应的资源项。所有的这些整形数,都以常量的方式,整合到一个Java类中,这个类就是
R类。这样,在程序中,就可以通过使用这个R类,来查找所需的资源,这就将字符串比较,简化成了一个整形数的比较,大大的节约了开销。
不得不说,这整套逻辑和Symbian中的资源文件预编译一致。但两者很不同的点在于Symbian中的整形数,代表的是一个二进制流的
偏移量,资源中的内容在编译时决定了。而Android中的整形数,是一个有
逻辑意义的数值,它表达了这个资源所处的资源包,类别,和脚标,它的具体内容在运行时才确定,这使得它的
灵活性大大增强,付出的则是一定的
效率代价。
实现
按照惯例,还是要说实现的,以一个查找流程为示例。当在
Activity中需要使用字符串的,会调用它的
getString方法,传入
R.stirng.xxx的一个整形数,换取一个符合当前机器环境配置的字符串。
getString,追根溯源,来到
AssetManager类中。Asset类,其实是一个空壳,它仅仅是提供了一些便利的接口,而将请求,通过
JNI的接口,传入到了
底层C++实现的类库中。
在底层的实现,主要是在C++实现的,AssetManager,ResourceTypes等等之中。其中:
- JNI文件在:framework/base/core/jni
- 头文件在:framework/base/include/utils
- CPP文件在:framework/base/libs/utils
具体实现,和前述的算法逻辑是一致的。每一个资源的id,32位,
高8位表示资源包,
低16位用于描述脚标,
中间8位,用来说明类别。所有资源中的文件,都被预处理了,放入到了一系列的队列和表中,通过id,可以查到具体的位置。然后根据缓存的环境设置对象,跑一次淘汰算法,获得匹配的资源对象的对应文件和偏移量。然后将值读取出来,通过JNI接口,拷贝回去。
以上这些描述,并不能帮助了解真实的实现细节,主要是为了促使大家对读取资源的效率有一个比较直观的认知。整个资源读取的流程比较长,但是实现在C++中,可以预想,效率比Java高一些,开发人员,应该能够根据自己的需求,决定是否将内容写入资源文件中(还是写在代码中...),是不是需要自己稍微缓存一下,诸如此类。
========================================
申请了自己的空间和域名,总算有了家的感觉,有兴趣的可以移步
flyvenus.net,会同步更新相关内容,并提供更好的阅读体验。
========================================