android 知识点总结 广播接收器生命周期【爱扒拉】

http://www.aibala.com/bbs/read.php?tid=7169

<DIV id=read_377 mb10?>广播接收器生命周期
广播接收器只有一个回调方法:
void onReceive(Context curContext, Intent broadcastMsg)
当广播消息抵达接收器时,Android调用它的onReceive()方法并将包含消息的Intent对象传递给它。广播接收器仅在它执行这个方法时处于活跃状态。当onReceive()返回后,它即为失活状态。
拥有一个活跃状态的广播接收器的进程被保护起来而不会被杀死。但仅拥有失活状态组件的进程则会在其它进程需要它所占有的内存的时候随时被杀掉。
这种方式引出了一个问题:如果响应一个广播信息需要很长的一段时间,我们一般会将其纳入一个衍生的线程中去完成,而不是在主线程内完成它,从而保证用户交互过程的流畅。如果onReceive()衍生了一个线程并且返回,则包涵新线程在内的整个进程都被会判为失活状态(除非进程内的其它应用程序组件仍处于活跃状态),于是它就有可能被杀掉。这个问题的解决方法是令onReceive()启动一个新服务,并用其完成任务,于是系统就会知道进程中仍然在处理着工作。
下一节中,我们会讨论更多进程易误杀的问题。
进程与生命周期
Android系统会尽可能长的延续一个应用程序进程,但在内存过低的时候,仍然会不可避免需要移除旧的进程。为决定保留或移除一个进程,Android将每个进程都放入一个“重要性层次”中,依据则是它其中运行着的组件及其状态。重要性最低的进程首先被消灭,然后是较低的,依此类推。重要性共分五层,依据重要性列表如下:
1.      前台进程是用户操作所必须的。当满足如下任一条件时,进程被认为是处于前台的:
o        它运行着正在与用户交互的activity(Activity对象的onResume()方法已被调用)。
o        一个正在与用户交互的activity使用着它提供的一个服务。
o        它包含着一个正在执行生命周期回调方法(onCreate()、onStart()或onDestroy())的Service对象。
o        它包含着一个正在执行onReceive()方法的BroadcastReceiver对象。
任一时间下,仅有少数进程会处于前台,仅当内存实在无法供给它们维持同时运行时才会被杀死。一般来说,在这种情况下,设备已然处于使用虚拟内存的状态,必须要杀死一些前台进程以用户界面保持响应。
2.      可视进程没有前台组件,但仍可被用户在屏幕上所见。当满足如下任一条件时,进程被认为是可视的:、
o        它包含着一个不在前台,但仍然为用户可见的activity(它的onPause()方法被调用)。这种情况可能出现在以下情况:比如说,前台activity是一个对话框,而之前的activity位于其下并可以看到。
o        它包含了一个绑定至一个可视的activity的服务。
可视进程依然被视为是很重要的,非到不杀死它们便无法维持前台进程运行时,才会被杀死。
3.      服务进程是由startService()方法启动的服务,它不会变成上述两类。尽管服务进程不会直接为用户所见,但它们一般都在做着用户所关心的事情(比如在后台播放mp3或者从网上下载东西)。所以系统会尽量维持它们的运行,除非系统内存不足以维持前台进程和可视进程的运行需要。
4.      背景进程包含目前不为用户所见的activity(Activity对象的onStop()方法已被调用)。这些进程与用户体验没有直接的联系,可以在任意时间被杀死以回收内存供前台进程、可视进程以及服务进程使用。一般来说,会有很多背景进程运行,所以它们一般存放于一个LRU(最后使用)列表中以确保最后被用户使用的activity最后被杀死。如果一个activity正确的实现了生命周期方法,并捕获了正确的状态,则杀死它的进程对用户体验不会有任何不良影响。
5.      空进程不包含任何活动应用程序组件。这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间。系统经常会杀死这种进程以保持进程缓存和系统内核缓存之间的平衡。
Android会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别。比如说,如果一个进程中同时有一个服务和一个可视的activity,则进程会被判定为可视进程,而不是服务进程。
此外,一个进程的级别可能会由于其它进程依赖于它而升高。一个为其它进程提供服务的进程级别永远高于使用它服务的进程。比如说,如果A进程中的内容提供者为进程B中的客户端提供服务,或进程A中的服务为进程B中的组件所绑定,则A进程最低也会被视为与进程B拥有同样的重要性。
因为运行着一个服务的进程重要级别总高于一个背景activity。所以一个activity以启动一个服务的方式启动一个长时间运行过程比简单的衍生一个线程来进行处理要好。尤其是当处理过程比activity本身存在时间要长的情况之下。我们以背景音乐播放和上传一个相机拍摄的图片至网站上为例。使用服务则不论activity发生何事,都至少可以保证操作拥有“服务进程”的权限。如上一节广播接收器生命周期所提到的,这也正是广播接收器使用服务,而不是使用线程来处理耗时任务的原因。

用户界面User Interface
在一个Android应用中,用户界面是由View和ViewGroup对象构建的。View与ViewGroup都有很多种类,而它们都是View类的子类。

View对象是Android平台中用户界面体现的基础单位。View类是它称为“widgets(工具)”的子类的基础,它们提供了诸如文本输入框和按钮之类的UI对象的完整实现。ViewGroup类同样为其被称为“Layouts(布局)”的子类奠定了基础,它们提供了象流式布局、表格布局以及相对布局之类的布局架构。

View对象是一个数据体,它的属性存储了用于屏幕上一块矩形区域的布局参数及内容。并负责这块它所辖的这个矩形区域之中所有测量、布局、焦点转换、卷动以及按键/触摸手势的处理。作为一个用户界面对象,View同时也担任着用户交互关键点以及交互事件接受者的角色。

视图层次View Hierarchy
在Android平台上,你可以用下图所示的View和ViewGroup层次图来定义一个Activity的UI。这个层次树可随你所愿的简单或者复杂化,你能使用Android预定义的一套工具和布局来创建它,或者使用你自己定义的Views来创建。
为了把一个视图层次树展现到屏幕上,你的Activity必须调用setContentView()方法,并传给它一个根节点对象的引用。Android系统将接受此引用,并用来进行界面的废止、测量并绘制这棵树。层次的根结点会要求它的子节点进行自我绘制──进而,每个视图组节点也负责调用它的子视图进行自我绘制。子节点将向父节点申请绘制的位置以及大小,而其父类享有子节点绘制的位置及大小的最终决定权。Android依次(自层次树顶层开始)解析你布局中的元素,实例化View并将它们添加到它们的父节点中。因为这个过程是依次进行的,所以如果出现了元素重叠的情况,最后一个绘制的元素将位于所有重叠元素之上显现。

如欲获得更多关于视图层次如何测算以及绘制细节的讨论,情参阅Android如何绘制视图。
布局Layout
定义并展现你的视图层次的最常用的方法是使用XML布局文件。如同HTML一样,XML为布局提供了一种可读的结构。XML中的每个元素都是View或ViewGroup对象(抑或它们的子类)。View对象是树的叶节点,而ViewGroup对象是树的分支(参阅楼上的视图层次图)。
XML元素的名称与它体现的Java类相对应。所以一个<TextView>元素将在你的UI中生成一个TextView,而<LinearLayout>则创建一个LinearLayout视图组。当你载入一个布局资源时,Android系统会根据你布局中的元素初始化这些运行时对象。
举例来说,一个包含文本视图和一个按钮的简单垂直布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>
请注意:LinearLayout 元素包含了TextView 和Button 对象。你可以在其中另外安置一个LinearLayout (或其它类型的视图组),以延展这个视图层次,构建更复杂的布局。
欲获知更多如何构建UI布局的内容,请参阅声明布局。
提示:您也可以用Java代码来绘制View和ViewGroup对象,并用addView(View)方法动态的插入新的View和ViewGroup对象。
您有相当多的方法来对视图进行布局。使用大量不同种类的视图组,您可以有近乎无穷的方式来构建子视图和视图组。Android提供了一些预定义的视图组,其中包括LinearLayout, RelativeLayout, AbsoluteLayout, TableLayout, GridLayout以及其它的一些。每个都为定义子视图和布局结构提供了一套独特的布局参数。
欲了解其它用于布局的不同种类的视图组,请参阅普通布局对象。
部件Widgets
部件是为用户交互界面提供服务的视图对象。Android提供了一套完整的部件实现,包括按钮、复选框、文本输入框等,以助于你快速的构建UI。Android还提供了一些更高级的部件,比如日期选择、时钟以及缩放控制。但您并没有被局限于Android平台提供的这些部件上。如果您想创建一些您自己的定制动作元素,您可以这么做,只要定义自己的视图对象或者扩展或合并现有的部件就行。
更多信息参阅构建自定义组件。
您可以在android.widget包中找到Android提供的部件列表。
用户界面事件UI Events
当你在用户界面中加入了一些视图和工具之后,你可能想要知道如何让它们与用户交互,进而实现你的动作。如欲获得用户界面事件通知,你需要做以下两件事情之一:

    * 定义一个事件侦听器并将其注册至视图。通常情况下,这是你侦听事件的主要方式。View类包含了一大堆命名类似 On<什么什么>Listener的接口,每个都带有一个叫做On<什么什么>()的回调方法。比如:View.OnClickListener (用以处理视图中的点击),View.OnTouchListener(用以处理视图中的触屏事件),以及View.OnKeyListener (用以处理视图中的设备按键事件)。所以,如果你希望你的视图在它被”点击”(比如选择了一个按钮)的时候获得通知,你就要实现OnClickListener,定义它的onClick()回调方法(在其中进行相应处理),并将它用setOnClickListener()方法注册到视图上。
    * 为视图覆写一个现有的回调方法。这种方法主要用于你自己实现了一个View类,并想侦听其上发生的特定事件。比如说当屏幕被触摸(onTouchEvent()),当轨迹球发生了移动(onTrackballEvent())或者是设备上的按键被按下(onKeyDown())。这种方式允许你为自己定制的视图中发生的每个事件定义默认的行为,并决定是否需要将事件传递给其它的子视图。再说一次,这些是View类相关的回调方法,所以你只能在你构建自定义组件时定义它们。

如何在视图中处理用户交互请参见处理用户界面事件文档。

菜单Menus
应用程序菜单是应用程序用户界面中另外一个重要的组成部分。菜单为展现应用程序功能和设置提供了一个可靠的界面。按下设备上的MENU键会调出最普通的应用程序菜单。然而,你也可以加入当用户长按一个项目时调出的上下文菜单。
菜单也是用视图层次进行构架的,但你不必自己定义这个架构。你只要为你的Activity定义onCreateOptionsMenu()和onCreateContextMenu()回调方法,并声明你想要包含在菜单中的项目就行了。Android将为你的菜单自动创建视图层次,并在其中绘入你的菜单项。
菜单会自行处理它们的事件,所以你不必为你菜单中的项目注册事件侦听器。当你菜单中的一项被选定时,框架将自动调用onOptionsItemSelected()或onContextItemSelected()方法。
如同应用程序布局一样。你也可以在一个XML文件中定义你菜单中的项目。
更多信息,请参阅创建菜单。
高级话题Advanced Topics
一旦你对创建用户界面的基础了如指掌,你就可以尝试着用一些高级功能来创建更加复杂的应用程序界面。
适配器Adapter
有时候你会想要用一些无法硬编码的信息来填充视图组。你想将源于外部的数据绑定到你的视图中。为达到这个目的,你可以使用AdapterView作为你的视图组,并用Adapter传来的数据初始化每个子视图并填入其中。
AdapterView对象是一个用给定的Adapter对象为基础构建它的子视图的ViewGroup实现。而Adapter在你的数据源(可能是一个外部字符串数组)和显示这些数据的AdapterView之间扮演着一个信使的角色。针对特定的任务有着很多不同的Adapter类实现,比如CursorAdapter依据Cursor读出一个数据库的数据,而一个ArrayAdapter则从任一个数组进行读取。
想要了解如何运用Adapter填充你的视图,请参见用AdapterView绑定至数据。
风格与主题Styles and Themes
或许你对标准工具的外表不是那么满意。为了解决这个问题,你可以创建你自己的风格和主题。

    * 风格是一套包含一个或多个格式化属性的整体,你可以把它们加诸于你布局中的单个元素之上。比如,你可以定义一个包含特定文本字体大小和颜色的风格,并将它单独施用于特定的视图元素。
    * 主题也是一套包含一个或多个格式化属性的整体,但却应用于一个应用程序中的所有Activity,或单独一个Activity。比如说,你可以定义一个包含了特定窗口边框颜色和版面背景、以及一套字体大小和菜单颜色的主题。这个主题可以施用于特定的Activity抑或整个应用程序。

风格与主题隶属于资源。Android提供了一些默认的风格和主题供你使用,你也可以定制你自己的风格和主题资源。

想了解更多关于使用风格和主题的内容,请参阅使用风格和主题文档。

资源和资产Resources and Assets

资源是Android应用程序不可或缺的部分。总体而言,资源是你想包含和引入到应用程序里面的一些外部元素,比如图片、音频、视频、文本字符串、布局、主题等。每个Android应用程序包含一个资源目录(res/)和资产目录(assets/),资产不经常被使用,因为它们的应用程序很少。你仅在需要读取原始字节流时才需要保存数据为资产。资源和资产目录均驻留在Android项目树的顶端,和源代码目录(src/)处在同一级上。
资源和资产从表面上看没多大区别,不过总体上,在存储外部内容时资源用得更多。真正的区别在于任何放置在资源目录里的内容可以通过您的应用程序的R类访问,这是被Android编译过的。而任何存放在资产目录里的内容会保持它的原始文件格式,为了读取它,你必须使用AssetManager来以字节流的方式读取文件。所以保持文件和数据在资源中(res/)中会更方便访问。
在这篇文章中,你将获取关于Android应用程序经常使用的标准资源类型以及如何在代码中引用方面的信息。资源和国际化(Resources and Internationalization)是第一步,可以知道Android如何利用项目资源。然后,可用资源类型(Available Resource Types)汇总描述了各种资源类型及其规格引用。

资源和国际化Resources and Internationalization
资源是外部文件(即非源代码文件),它们被你的代码使用,并且在编译时被编译到你的应用程序中。Android支持很多不同类型的资源文件,包括XML、PNG和JPEG文件。XML文件会由于其所描述的内容不同而形式不同。该文档描述了所有支持的文件类型及每种类型的语法或格式。
资源从源代码中被抽取出来,基于效率考虑,XML文件被编译成二进制、可以快速加载的形式。字符串,同样被压缩为一种更富效率的存储形式。由于这些原因,在Android平台中我们就有了这些不同的资源类型。
这是一篇纯粹的技术性文档,它和可用资源(Available Resources)一起覆盖了有关资源的众多信息。在使用Android时并不需要记住这篇文档,但是当你需要它时你应该知道来这里寻找信息。
介绍Introduction
这个话题包含了与之相应的术语列表,和一系列在代码中使用资源的实例。关于Android支持的所有资源类型的完整指南,请查阅可用资源(Available Resources)。
Android资源系统记录应用程序中所有非代码资产。你可以使用Resources类来访问应用程序中的资源;一般可以通过Context.getResources()获得这个Resources实例。
一个应用程序的资源在生成(build)时被编译器编译到应用程序的二进制文件中。要使用一个资源,你必须把它放置到源代码树中的正确位置,并且生成(build)到你的应用程序中。作为编译过程的一部分,每个资源的标记都会被生成,在你的源代码中可以使用这些标记-这允许编译器验证你的应用程序代码是否和你定义的资源相匹配。
本部分的其余内容以一个在应用程序中如何使用资源的指南的形式组织。
创建资源Creating Resources
Android支持字符串、位图以及其他很多种类型的资源。每一种资源的语法、格式以及存放的位置,都会根据其类型的不同而不同。通常,你创建的资源一般来自于三种文件:XML文件(除位图和raw之外的任何文件)、位图文件(图像)以及Raw文件(除前面以外的其他东西,如声音文件,等等)。事实上,XML文件也有两种不同的类型:被原封不动地编译进包内的文件和被aapt用来产生资源的文件。这里有一个每种资源类型的列表,包括文件格式、文件描述以及XML文件类型的细节。
你可以在你的项目中的res/目录的适当的子目录中创建和保存资源文件。Android有一个资源编译器(aapt),它依照资源所在的子目录及其格式对其进行编译。这里有一个每种资源的文件类型的列表,关于每种类型的描述、语法、格式以及其包含文件的格式或语法见资源参考。
表一
目录Directory
    
资源类型Resource Types
res/anim/
    
XML文件,它们被编译进逐帧动画(frame by frame animation)或补间动画(tweened animation)对象
res/drawable/
    
.png、.9.png、.jpg文件,它们被编译进以下的Drawable资源子类型中:
要获得这种类型的一个资源,可以使用Resource.getDrawable(id)
位图文件
9-patches(可变尺寸的位图)
为了获取资源类型,使用mContext.getResources().getDrawable(R.drawable.imageId)
注意:放在这里的图像资源可能会被aapt工具自动地进行无损压缩优化。比如,一个真彩色但并不需要256色的PNG可能会被转换为一个带调色板的8位PNG。这使得同等质量的图片占用更少的资源。所以我们得意识到这些放在该目录下的二进制图像在生成时可能会发生变化。如果你想读取一个图像位流并转换成一个位图(bitmap),请把图像文件放在res/raw/目录下,这样可以避免被自动优化。
res/layout/
    
被编译为屏幕布局(或屏幕的一部分)的XML文件。参见布局声明(Declaring Layout)
res/values/
    
可以被编译成很多种类型的资源的XML文件。
注意:不像其他的res/文件夹,它可以保存任意数量的文件,这些文件保存了要创建资源的描述,而不是资源本身。XML元素类型控制这些资源应该放在R类的什么地方。
尽管这个文件夹里的文件可以任意命名,不过下面使一些比较典型的文件(文件命名的惯例是将元素类型包含在该名称之中):
*                   array.xml定义数据
*                   colors.xml定义color drawable和颜色的字符串值(color string values)。使用Resource.getDrawable()和Resources.getColor()分别获得这些资源。
*                   dimens.xml定义尺寸值(dimension value)。使用Resources.getDimension()获得这些资源。
*                   strings.xml定义字符串(string)值(使用Resources.getString()或者Resources.getText()获取这些资源。getText()会保留在UI字符串上应用的丰富的文本样式)。
·                                 styles.xml定义样式(style)对象。
res/xml/
    
任意的XML文件,在运行时可以通过调用Resources.getXML()读取。
res/raw/
    
直接复制到设备中的任意文件。它们无需编译,添加到你的应用程序编译产生的压缩文件中。要使用这些资源,可以调用Resources.openRawResource(),参数是资源的ID,即R.raw.somefilename。

资源被编进最终的APK文件中。Android创建了一个封装类,叫做R,在代码中你可以使用它来引用这些资源。R包含了根据资源文件的路径和名称命名的子类。
全局资源说明Global Resource Notes
一些资源允许你定义颜色值。Android接受的颜色值可以使用多种web样式的形式--以下几种包含十六进制常数的形式:#RGB、#ARGB、#RRGGBB、#AARRGGBB。
所有颜色值支持设置透明度(alpha channel value),前两位的十六进制数指定了透明了。0在透明度值是全透明。默认值是不透明。
使用资源Using Resources
这一部分描述如何使用你创建的资源。它包含以下主题:
l         代码中使用资源 - 如何在你的代码中调用资源进行实例化。
l         从其他资源中引用资源 - 你可以从其他资源中引用资源。这就使得你可以重用资源中公共资源值。../../Docs/android_dev_guide/android_dev_guide/developer.android.com/guide/topics/resources/resources-i18n.html - ReferencesToResources
l         支持针对交替配置的交替资源 - 你可以根据主机硬件的语言或显示配置指定加载不同的资源。
在编译时,Android产生一个名为R的类,它包含了你的程序中所有资源的资源标识符。这个类包含了一些子类,每一个子类针对一种Android支持的资源类型,或者你提供的一个资源文件。每一个类都包含了已编译资源的一个或多个资源标识符,你可以在代码中使用它们来加载资源。下面是一个小的资源文件,包含了字符串、布局(屏幕或屏幕的一部分)和图像资源。
注意:R类是一个自动产生的文件,并没有设计为可以手动编辑。当资源更新时,它会根据需要重新产生。
package com.google.android.samples;
public final class R {
public static final class string {
public static final int greeting = 0x0204000e;
public static final int start_button_text = 0x02040001;
public static final int submit_button_text = 0x02040008;
public static final main_screen_title = 0x0204000a;
};
public static final class layout {
public static final int start_screen = 0x02070000;
public static final int new_user_pane = 0x02070001;
public static final int select_user_list = 0x02070002;
};
public static final class drawable {
public static final int company_logo = 0x02020005;
public static final int smiling_cat = 0x02020006;
public static final int yellow_fade_background = 0x02020007;
public static final int stretch_button_1 = 0x02020008;
};
};
在代码中使用资源Using Resources in Code
在代码中使用资源,只是要知道所有资源ID和你的被编译的资源是什么类型。下面是一个引用资源的语法:
R.resource_type.resource_name



或者

android.R.resource_type.resource_name



其中resource_type是R的子类,保存资源的一个特定类型。resource_name时在XML文件定义的资源的name属性,或者有其他文件类型为资源定义的文件名(不包含扩展名)。每一种资源类型都会根据其类型加为一个特定的R子类;要了解R的哪一个子类是关于你的资源类型的,请参考资源参考(resource reference)文档。被你的应用程序编译的资源可以不加包名引用(就像R.resource_type.resource_name这样简单)。Android包含了很多标准资源,如屏幕样式和按钮背景。要在代码中引用这些资源,你必须使用android进行限定,如android.R.drawable.button_background。

这里有一些在代码中使用已编译资源的正确和错误用法的例子。
// Load a background for the current screen from a drawable resource.
this.getWindow().setBackgroundDrawableResource(R.drawable.my_background_image);
// WRONG Sending a string resource reference into a
// method that expects a string.
this.getWindow().setTitle(R.string.main_title);
// RIGHT Need to get the title from the Resources wrapper.
this.getWindow().setTitle(Resources.getText(R.string.main_title));
// Load a custom layout for the current screen.
setContentView(R.layout.main_screen);
// Set a slide in animation for a ViewFlipper object.
mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.hyperspace_in));
// Set the text on a TextView object.
TextView msgTextView = (TextView)findViewByID(R.id.msg);
msgTextView.setText(R.string.hello_message);

引用资源References to Resources
在属性(或资源)中提供的值也可以作为资源的引用。这种情况经常使用在布局文件中,以提供字符串(因此它们可以被本地化<将UI上的字符串放在一个单独的文件中,在做国际化时只需要将它们翻译成相应的语言版本,然后应用程序根据locale信息加载相应的字符串文件——译者注>)和图像(它们存在于另外的文件中),虽然引用可以是任何资源类型,包括颜色和整数。
例如,如果我们有颜色资源(color resources),我们可以编写一个布局文件,将文本的颜色设为那些资源中包含的值:
<?xml version="1.0" encoding="utf-8"?>
<EditText id="text" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textColor="@color/opaque_red"
android:text="Hello, World!" />
注意,这里使用“@”前缀引入对一个资源的引用——在@[package:]type/name形式中后面的文本是资源的名称。在这种情况下,我们不需要指定包名,因为我们引用的是我们自己包中的资源。要引用系统资源,你应该这样写:
<?xml version="1.0" encoding="utf-8"?>
<EditText id="text" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textColor="@android:color/opaque_red"
android:text="Hello, World!" />
另外一个例子,当在布局文件中提供字符串以便于本地化时,你应该一直使用资源引用。
<?xml version="1.0" encoding="utf-8"?>
<EditText id="text" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textColor="@android:color/opaque_red"
android:text="@string/hello_world" />
这种技巧还可以用来创建资源之间的引用。例如,我们可以创建新的drawable资源作为已存在资源的别名。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable id="my_background">@android:drawable/theme2_background</drawable>
</resources>

引用主题属性References to Theme Attributes
另外一种资源值允许你引用当前主题中的属性的值。这个属性值只能在样式资源和XML属性中使用;它允许你通过将它们改变为当前主题提供的标准变化来改变UI元素的外观,而不是提供具体的值。
如例中所示,我们在布局资源中使用这个特性将文本颜色设定为标准颜色的一种,这些标准的颜色都是定义在基本系统主题中。
<?xml version="1.0" encoding="utf-8"?>
<EditText id="text" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textColor="?android:textDisabledColor"
android:text="@string/hello_world" />
注意,这和资源引用非常类似,除了我们使用一个“?”前缀代替了“@”。当你使用这个标记时,你就提供了属性资源的名称,它将会在主题中被查找——因为资源工具知道需要的属性资源,所以你不需要显示声明这个类型(如果声明,其形式就是?android:attr/android:textDisabledColor)。
除了使用这个资源的标识符来查询主题中的值代替原始的资源,其命名语法和“@”形式一致:?[namespace:]type/name,这里类型可选。

使用系统资源Using System Resources
在系统中的包含了很多应用程序可以使用的资源。所有的这些资源都在“android.R”类下定义。例如,使用下面的代码你可以在屏幕上显示标准应用程序的图标:
public class MyActivity extends Activity {
public void onStart() {
requestScreenFeatures(FEATURE_BADGE_IMAGE);
super.onStart();
setBadgeResource(android.R.drawable.sym_def_app_icon);
}
}
以相似的方式,下面的代码将对你的屏幕应用系统定义的标准“绿色背景”视觉处理。
public class MyActivity extends Activity
public void onStart() {
super.onStart();
setTheme(android.R.style.Theme_Black);
}
}

替换资源(为了可替换的资源和配置)Alternate Resources
你可以根据UI语言或者设备上的硬件配置,为你的产品提供不同的资源。注意,尽管你可以包含不同的字符串、布局和其他资源,然而SDK没有方法供你指定加载哪一个替换资源。Android检测关于硬件和未知的适当配置,然后适当加载。用户可以使用设备上的设置面板选择替换语言设置。
为了包含替换资源,需要创建平行的资源文件夹,而文件夹的名字后面要使用限定符表示它要应用的配置(语言、屏幕方向等等)。例如,下面的工程包含了字符串资源,一个用于英语,而另外一个用于法语:
MyApp/
res/
values-en/
strings.xml
values-fr/
strings.xml
Android支持几种类型的限定符,每一个都有不同的值。把它们连接在资源文件夹名称的后面,使用短横线隔开。你可以为每一个文件夹名称添加多个限定符,但是它们必须按照这里列出的顺序排列。例如,一个包含drawable资源的文件夹,对于一个完整详细的配置,可能看起来像:
MyApp/
res/
values-en/
drawable-en-rUS-port-160dpi-finger-qwerty-dpad-480x320/
更典型的是,你只需指定一些特定的要定义资源的配置选项。你可以放弃完整列表中的任何值,但同时要保证剩下的值仍然保持列表中的顺序。
MyApp/
res/
drawable-en-rUS-finger/
drawable-port/
drawable-port-160dpi/
drawable-qwerty/

表2 列举了合法的限定符目录名称,按优先级排序。下表中列举在上面的限定符比下面的具有更高的优先级,如同Android如何查找最匹配的目录中所描述的那样。
表2
限定符Qualifier
    
值Values
移动国家码MCC和移动网络码MNC
    
手机设备SIM卡上的移动国家码和移动网络码。比如mcc310-mnc004 (美国,Verizon品牌); mcc208-mnc00 (法国, Orange品牌); mcc234-mnc00 (英国,BT品牌).

如果这个设备使用一个无线连接(GSM电话),则MCC来自SIM卡,而MNC来自该设备将要附着的网络。你有时会仅使用MCC,例如包含特定国家合法资源在您的应用程序中。如果您的应用程序指定了MCC/MNC组合的资源,这些资源仅在MCC和MNC都匹配的时候才能使用。
语言和区域Language and region
    
两个字母的ISO 639-1语言码和ISO 3166-1-alpha-2区域码 (以"r"为前缀)。比如en-rUS, fr-rFR, es-rES.

这个代码是大小写敏感的:语言码是小写字母,国家码是大写字母。你不能单独指定一个区域,但是你可以单独指定一个语言,比如en, fr, es, zh.
屏幕方向Screen orientation
    
纵向,横向,正方形(port, land, square)
屏幕像素密度Screen pixel density
    
92dpi, 108dpi等. 当Android选择使用哪个资源时,它对屏幕像素密度的处理和其它限定符不同。在文章后面描述的步骤1Android如何查找最匹配的目录中,屏幕密度总被认为是匹配的。在步骤4中,如果被考虑的限定符是屏幕密度,Android将选择在那个位置的最佳匹配,而无需继续步骤5。
触摸屏类型Touchscreen type
    
非触摸式,触摸笔,手指(notouch, stylus, finger)
键盘可用方式Whether the keyboard is available to the user
    
外在键盘,隐藏键盘,软键盘(keysexposed, keyshidden, keyssoft)
如果你的应用程序有一个特定的资源只能通过软件盘使用,则使用keyssoft值,如果没有keyssoft资源可用(只有keysexposed和 keyshidden)并且该设备显示了一个软键盘,那么系统将使用keysexposed资源。
首选文本输入方法Primary text input method
    
不支持按键,标准键盘,12键(nokeys, qwerty, 12key)
首选非触摸式导航方法Primary non-touchscreen
navigation method
    
不支持导航,滑板,跟踪球,滚轮(nonav, dpad, trackball, wheel)
屏幕分辨率Screen dimensions
    
320x240, 640x480, 等. 更大的分辨率必须先被指定。
SDK版本SDK version
    
设备支持的SDK版本,比如v3。Android1.0 SDK是v1,1.1SDK是v2,1.5SDK是v3。
小版本(Minor version)
    
你目前还不能指定小版本,它总是被设置为0。
这个列表不包含设备特有的参数比如载波,品牌,设备/硬件,或者制造商。所有应用程序需要知道的设备信息均通过上表中的资源限定符编码。
所有资源目录,许可的和未经许可的,都存放在res/目录下。下面是一些关于许可的资源目录名称的指导原则:
l         你可以指定多个限定符,用破折号分开。比如,drawable-en-rUS-land会被应用在美国英语的横向手机设备中。
l         限定符必须符合表2中列举的顺序。比如:
*       正确的:values-mcc460-nokeys/
*       错误的:values-nokeys-mcc460/
l         限定符的值大小写敏感。比如一个纵向特定的drawable目录必须命名为drawable-port,不可以是drawable-PORT或drawable-Port。
l         每个限定符类型仅支持一个值。比如,如果你想使用为法国和西班牙使用相同的drawable文件,你得需要两个资源目录,如drawable-rES/和drawable-rFR/,包含相同的文件。你不能使用一个名为drawable-rES-rFR的目录。
l         限定符不能嵌套使用。比如,你不能使用res/drawable/drawable-en。
资源怎么在代码中使用How resources are referenced in code
所有的资源均通过它们简单未经修饰的名字在代码或资源引用语法中引用。所以如果一个资源命名如下:
    MyApp/res/drawable-port-92dpi/myimage.png
它会被这样引用:
    R.drawable.myimage (code)
    @drawable/myimage (XML)
如果有多个drawable目录可用, Android将会选择其一(如下所述)并从中加载myimage .png。
AndroidHow Android finds the best matching directory如何查找最匹配的目录
Android将从各种潜在的资源中挑选出哪个应该在运行时使用,这取决于设备的当前配置。这里的例子假定使用了如下的设备配置:
区域Locale = en-GB
屏幕方向Screen orientation = port
屏幕像素密度Screen pixel density = 108dpi
触摸屏类型Touchscreen type = notouch
首选文本输入方式Primary text input method = 12key
下面说明了Android如何作出选择:
1.         排除和设备配置冲突的资源文件。比如,假定如下的drawables资源目录可用。那么drawable-fr-rCA/会被排除,因为它和设备的区域配置冲突。
MyApp/res/drawable/
MyApp/res/drawable-en/
MyApp/res/drawable-fr-rCA/
MyApp/res/drawable-en-port/
MyApp/res/drawable-en-notouch-12key/
MyApp/res/drawable-port-92dpi/
例外:屏幕像素密度是唯一不用来排除文件的限定符。即使设备屏幕密度是108dpi,drawable-port-92dpi/也不会被从列表中排除,因为在这里所有的屏幕密度都被视为匹配。
2.         从表2中选取最高优先级的限定符(从MCC开始,然后自该列表依次往下)。
3.         有没有哪个可用的资源目录包含了这个限定符?
&sup2;        如果没有,回到步骤2然后查看表2中所列的下一个限定符。在我们的例子中,答案是“没有”直到我们到达语言这一级。If No, return to step 2 and look at the next qualifier listed in Table 2. In our example, the answer is "no" until we reach Language;
&sup2;        如果有,则跳转到步骤4。
4.         排除不包含这个限定符的资源目录,在我们的例子中,我们排除所有不包含语言的目录。
MyApp/res/drawable/
MyApp/res/drawable-en/
MyApp/res/drawable-en-port/
MyApp/res/drawable-en-notouch-12key/
MyApp/res/drawable-port-92dpi/
MyApp/res/drawable-port-notouch-12key
例外:如果询问中的限定符是屏幕像素密度,Android会选择最接近匹配于设备的选项,而且选择过程将会完成。一般而言,Android会倾向于缩小一个大图片而不是放大一个小图片。
5.         回头重复步骤2,3,4直到只剩下一个选择。在本例中,屏幕方向是下一个要比较的限定符,我们排除没有指定屏幕方向的资源。现在只剩下一个选择,那就是它了。当drawables被这个应用程序调用时,Android系统会从下面这个目录中加载资源:MyApp/res/drawable-en-port/
提示Tip:限定符的优先权比匹配的数目要重要得多。比如,在上面的步骤4中,列表中最后的选项包含三个限定符和设备匹配(方向,触摸屏类型,和输入法),而drawable-en只有一个参数匹配(语言)。但是,语言拥有更高的优先权,所以drawable-port-notouch-12key 被排除出局。
下面的流程图总结了Android如何选择资源目录来加载的过程:
术语Terminology
资源系统将一系列分散内容集合在一起形成最终的完整的资源功能,去帮助我们了解整个系统。这里有一些核心概念以及组件的概要说明,你在开发中将可能使用到:
资产Asset:应用程序的独立的数据块。这包含所有从java程序编译成的目标文件,图像 (例如PNG图片), XML文件等等。这些文件以一种特定的方式组织在一起,在程序最后打包时,它们被捆绑进一个单独的ZIP文件里。
aapt::Android最终文件打包工具。这个工具产生最终程序的ZIP文件。除了将资产元数据文件收集在一起,它也把资源定义解析到最终的二进制数据里。
资源表Resource Table: aapt工具产生的特殊的文件,描述了所有在程序/包里的资源。这个文件可以通过资源类来访问;它不能直接和应用程序接触。
资源Resource: 资源表里一条记录描述的是单一的命名值。大体上, 资源分成两种:元资源和包资源.
资源标识符Resource Identifier: 在资源表里所有的资源都被唯一的整数标识着。所有的代码中(资源描述,XML 文件,Java源代码)你可以直接使用符号名代替真实的整数数值。
元资源Primitive Resource: 所有元资源都可以被写成一个简单的字串,使用一定的格式可以描述资源系统里各种不同的基本类型:整数,颜色,字串,其他资源的引用,等等。像图片以及XML描述文件这些复杂资源,被以元字串资源储存,它们的值就是相关最终数据文件的路径。
包资源Bag Resource: 一种特殊类型的资源,不是简单的字符串,而是一个容纳名字/数值对的任意列表。每个名字本身就是资源标识,每个值可以容纳相同类型的字符串格式的数据作为一个普通资源。包资源支持继承:一个包里的数据能从其他包里继承,有选择地替换或者扩展能产生它自己的内容。
种类Kind: 资源种类是对于不同需求的资源标识符而言的。例如,绘制资源类常常实例化绘制类的对象,所以这些包含颜色以及指向图片或XML文件的字符串路径数据是原始数据。其它常见资源类型是字符串(本地化字符串),颜色(基本颜色),布局(一个指向XML文件的字串路径,它描述的是一个用户界面)以及风格(一个描述用户接口属性的包装资源)。还有一个标准的“attr”资源类型,它定义了命名包装数据以及XML属性的资源标识符。
风格Style: 包含包装资源类型的名字常常用来描述一系列用户接口属性。例如,一个TextView的类可能会有一个描述界面风格的类来定义文本大小,颜色以及对齐方式。在一个界面布局的XML文件中,可以使用“风格” 属性来确定整体界面风格,它的值就是风格资源的名字。
风格类Style Class: 这里将详述一些属性资源类。其实数据不会被放在资源表本身,通常在源代码里它以常量的形式出现,这也可以使你在风格类或者XML的标签属性里方便找到它的值。例如,Android平台里定义了一个“视图”的风格类,它包含所有标准视图的属性:画图区域,可视区域,背景等。这个视图被使用时,它就会借助风格类去从XML文件取得数据并将其载入到实例中。
配置Configuration: 对许多特殊的资源标识符,根据当前的配置,可以有多种不同的值。配置包括地区(语言和国家),屏幕方向,屏幕分辨率,等等。当前的配置用来选择当资源表载入时哪个资源值生效。
主题Theme: 一个标准类型的资源能为一个特殊的上下文提供全局的属性值。例如,当应用工程师写一个活动时,他能选择一个标准的主题去使用,白色的或者黑色的;这个类型能提供很多信息,如屏幕背景图片/颜色,默认文本颜色,按钮类型,文本编辑框类型,文本大小,等。当布置一个资源布局时,控件(文本颜色,选中后颜色,背景)的大部分设置值取自当前主题;如果需要,布局中的风格以及属性也可以从主题的属性中获得。
覆盖层Overlay: 资源表不能定义新类型的资源,但是你可以在其他表里替换资源值。就像配置值,这可以在装载时候进行;它能加入新的配置值(例如,改变字串到新的位置),替换现有值(例如,将标准的白色背景替换成"Hello Kitty"的背景图片),修改资源包(例如修改主题的字体大小。白色主题字体大小为18pt)。这实际上允许用户选择设备不同的外表,或者下载新的外表文件。

资源引用Resource Reference
可用资源Available Resources文档提供了一个各种类型资源的详细列表,并描述了如何在Java代码中或其他引用中使用它们。
国际化和本地化Internationalization and Localization
即将完成:国际化和本地化是非常关键的,但现在的SDK还没有完全准备好。当SDK成熟时,这个章节会包含Android平台国际化和本地化的相关信息。在此期间,让我们先从把资源外部化以及练习以好的结构创建和使用资源开始做起吧。


你可能感兴趣的:(android 知识点总结 广播接收器生命周期【爱扒拉】)