Android 四大组件详解
Android平台下四个核心组件分别是提供界面的Activity组件、提供后台计算的Service组件、提供广播接收的Broadcast Receiver组件、提供数据共享的Context Provider组件。不同组件具有不同的特性以及各自的声明周期,下面就来对每个组件进行详细的分析。
1.Activity组件
(1)Activity组件概述
Activity是最常见的一种Android组件,每个Activity都相当于一个屏幕,其为用户提供了进行交互的可视界面。应用程序可以根据需要包含一个或多个Activity,这些Activity一般都继承自android.app包下的Activity类,并且这些Activity之间的运行是相互独立的。
(2)Activity组件生命周期的3个阶段。
1)运行态(running state)
此时Activity显示在屏幕前台,并且具有焦点,可以和用户的操作进行交互。
2)暂停态(paused state)
此时Activity失去焦点,并被其它的运行态Activity取代在屏幕前台显示,暂停态的Activity仍然保留其状态和成员等其它信息,当系统的内存非常匮乏时,暂停态的Activity会被结束掉以获得更多的资源。
3)停止态(stopped state)
停止态的Activity不仅没有焦点,而且是完全不可见的,虽然其也保留状态和成员等信息,停止态的Activity会在系统需要的时候被结束。
(3)Activity组件要点
当Activity在不同的状态之间切换时,可以通过重写相应的回调方法来编写状态改变时应该执行的动作。
Activity之间通过Intent进行通信。
android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。
(4)Activity组件类图
(5)Activity的加载模式
Activity共有4中加载模式:standard、singleTop、singleTask和singleInstance。
1)standard加载模式
standard加载模式是Activity的默认加载模式,在加载时会创建一个新的Activity的实例,类似于调用startActivity方法时设置Intent的标志位Intent.FLAG_ACTIVITY_NEW_TASK。
2)singleTop加载模式
singleTop加载模式表示当前Activity的实例处于前台并可视时,该实例会收到发送过来的Intent消息。
3)singleTask加载模式
singleTask加载模式表示当前Activity栈(Task)中当前Activity实例运行时,该实例会收到相应的Intent消息,接收方法类似于singleTop加载模式。
4)singleInstance加载模式
singleInstance加载模式表示该Activity以单子模式加载,在当前Activity栈中唯一,接收方法类似于singleTop加载模式。
(6)Activity的属性配置
1)配置变化属性
android:mcc属性表示MCC,即SIM卡中存储的IMSI号中的国家代码部分,当发生国际漫游时,该属性配置会发生变化。
android:mnc属性表示MNC,即SIM卡中存储的IMSI号中的网络代码部分,当发生不用运营商网络间漫游时,该配置会发生变化。
android:locale属性表示当前显示的语言发生变化。
android:touchscreen属性表示触摸屏发生了变化,考虑当当前的实际情况,只有在支持多屏显示时才需要使用该属性。
android:keyboard属性表示键盘类型发生了变化,如外接蓝牙键盘等。
android:keyboardHidden属性表示显示或者隐藏键盘,对翻盖、滑盖终端有效。
android:navigation属性表示导航键发生了变化,如从轨道变化为五向键,考虑到当前的实际情况,该配置显然不会发生变化。
android:orientation属性表示屏幕方向,当前重力传感器几乎已经成为智能终端标配的情况下,需对该配置多加注意。
android:screenLayout属性表示屏幕布局发生变化。在不支持多屏显示的情况下,该配置不会发生变化。
android:fontScale属性表示字体发生了变化。
android:uiMode属性表示UI模式发生了变化,如变为车载模式、夜间模式等。
2)屏幕旋转属性
android:screenOrientation属性是Activity的一个重要属性,在有重力传感器的情况下,开发者必须考虑屏幕的适配情况。其属性值包括unspecified、landscape、portrait、user、behind、sensor和nosensor等。其中unspecified为默认值,旋转策略有系统决定;langscape表示横屏;portrait表示竖屏;user表示当前用户倾向的屏幕方向;behind表示屏幕方向和Activity栈中当前Activity下面的Activity相同;sensor表示根据重力传感器确定屏幕方向,这是一个重要的属性值;nosensor表示忽略传感器方向。
3)主题属性
android:thene属性表示当前Activity的主题。这是一个非常重要的属性,通常用于设置标题栏、状态栏等,当然也可以设置开发者自定义的主题
该属性的设置方法: android:theme=”@android:style/Theme.NoTitleBar“
4)启动约束属性
android:exported属性表示启动约束,即是否允许被其他进程调用,如果值为fase,则该Activity仅可被同一应用中的组件或拥有相应用户ID的应用的组件调用;如果值为true,则允许被其他进程调用。
android:exported属性的默认值与携带的Intent过滤器有关,如果没有携带任何Intent过滤器,则其值为false,否则为true。
2.Service组件
(1)Service组件概述
Service没有提供与用户进行交互的表示层。Service是运行在后台的一种Android组件,当应用程序需要进行某种不需要前台显示的计算或数据处理时,就可以启动一个Service来完成,每个Service都继承自android.app包下的Service类。
Service一般由Activity或其他Context对象来启动,当启动Service之后,该Service将会在后台运行,即使启动这个Service得Activity或其他组件的生命周期已经结束,Service仍然会继续运行,直到自己的生命周期结束为止。每个Service都应该在AndroidMainfest.xml中进行声明。
(2)Service组件的运行方式
服务的运行有两种方式,即绑定服务和启动服务。
1)通过startService方法启动
以启动服务的方式运行服务时,服务并不会随着绑定组件的销毁而销毁,而是服务会自我销毁,这种方式适用于文件加载、文件上传等请求后自行运行的场景。
当系统调用startService方法时,如果该Service还未启动,则依次调用其onCreate方法和onStart方法来启动。当其他Context对象调用stopService方法、Service调用自称的stopSelf或stopService方法时才会停止Service的执行。
2)通过bindService方法启动
当通过绑定服务的方式运行服务时,一旦绑定解除,服务即被销毁,当进行多次绑定时,只有所有的绑定均解除,服务才会销毁。
当系统调用bindService方法时,如果该Service未启动,则会调用其onCreate方法完成初始化工作,然后会将该Service和Context对象(如Activity)进行绑定,当被绑定的Context对象被销毁时,与之绑在一起的Service也会停止运行。
解除绑定时unbindService。
绑定服务时需要设置ServiceConection和标志位,ServiceConnection可以监控服务的状态,在进行服务绑定时,其标志位可以为BIND_AUTO_CREATE、BIND_DEBUG_UNBING和BIND_NOT_FOREGROUND等。
BIND_AUTO_CREATE表示当接收到绑定请求时,如果服务尚未创建,则即刻创建,在系统内存不足,需要销毁优先级组件来释放内存,且只有驻留该服务的进程成为被销毁对象时,服务才可被销毁。
BIND_DEBUG_UNBIND通常用于调试场景中判断绑定的服务是否正确,但其会引起内存泄露,因此非调试目的的不建议使用。
BIND_NOT_FOREGROUND表示系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行,该标志位在Froyo引入。
绑定服务时以异步的方式运行的。绑定服务必须在当前的上下文环境中进行,在某些场景中,如果无法绑定成功,则可能需要在应用级的上下文环境中进行。
(3)Service组件要点
需要注意的是,尽管存在两种方式启动Service,但是无论Service是通过什么方式启动的,都可以将其与Context对象进行绑定。
(4)Service组件类图
(5)服务生命周期流程图
3.Broadcast Receiver组件
(1)Broadcast Receiver组件概述
Broadcast Receiver也不提供与用户交互的表示层,其是一种负责接收广播消息并对消息作出反应的组件。在Android的系统中就存在许多这样的广播,比如电池电量过低或信号过低时,系统就会发出广播进行通知。广播的发送本质上是基于Intent进行的。
应用程序如果需要响应某个广播消息,应该注册对应的BroadcastReceiver对象,该对象继承自BroadcastReceiver类,该类位于Android.content包下。
(2)Broadcast Receiver组件广播方式
1)BroadcastReceiver发布广播的方式
发布一个广播比较容易,在需要的地方创建一个Intent对象,将信息的内容和用于过滤的信息封装起来,通过调用Context.sendBroadcast方法、Context.sendOrderedBroadcast方法或者Context.sendStickyBroadcast方法将该Intent对象广播出去,发布广播方式的区别如下。
通常,使用sendBroadcast或sendStickyBroadcast发送出去的Intent,所有满足条件的BroadcastReceiver都会执行其onReceive方法。但若有多个满足条件的BroadcastReceiver,其执行onReceive方法的顺序是没有保证的。
而通过sendOederedBroadcast方法发送出去的Intent,会根据BroadcastReceiver注册时IntentFilter设置的优先级的顺序来执行onReceive方法,相同优先级的BroadcastReceiver执行onReceiver方法的顺序是没有保证的。
sendStickyBroadcast主要的不同是,Intent在发送后会一直存在,并且在以后调用registerReceiver注册相匹配的Receiver时会把这个Intent对象直接返回给新注册的Receiver。
2)BroadcastReceiver接收广播的方式
发布的广播实体是Intent,那么接收广播的时候就需要通过IntentFilter对象来进行过滤。BroadcastReceiver的生命周期比较简单,只有一个回调方法--onReceive,该方法在应用程序接收到发给自己广播时候调用,所以BroadcastReceiver的使用方法也相对简单,只需要对onReceive方法进行合理重写,在适当的地方注册该Broadcast Receiver即可。
在AndroidMainfest.xml文件中声明。注册信息包含在<receiver></receiver>标签中,并在<intent-filter>标签内设定过滤规则。
在代码中创建并设置IntentFilter对象。该IntentFilter对象包含了对广播的过滤规则,然后再需要的地方调用Context.registerReceiver方法和Context.unregisterReceiver方法进行注册和取消注册,如果采用这种方式注册,当Context对象被销毁时,该BroadcastReceiver也就不复存在了。
4.Context Provider组件
(1)Context Provider组件概述
Context Provider和其它的应用程序组件有很大的不用,Context Provider主要用于不用的应用程序之间进行数据共享。在Android平台下,每个应用程序都有独立的内存空间,如果某个应用程序需要使用其它应用程序的数据,就必须采用ContextProvider对象。
(2)Context Provider组件要点
每个ContextProvider都继承自Android.context包下的ContextProvider类,其功能就是提供自己的数据给外部应用程序使用,提供的数据可以存储为Android文件、SQLite数据库文件或其他合法的格式。
ContextProvider提供数据及访问数据的接口,真正访问数据的是ContextResolver对象,该对象可以与ContextProvider对象进行通信,以达到共享数据的目的。
5.Intent组件
(1)Intent组件概述
Intent是Android用于进程内或进程间通信的机制,其底层的通信以Binder机制实现,在物理层上则以共享内存的方式来实现。
(2)Intent的应用场景
Intent主要用于两种场景:广播和发起意图,其属性有ComponentName、action、data、category、extras、flags等。在进行Intent的匹配时,需要匹配Action、data、category等3个属性。
1)ComponentName
ComponentName为处理Intent消息的Android组件,可以是Activity、服务等。通过调用setClassName方法设置。
2)action
action表示Intent的类型,可以是查看、删除、发布或其他,最常使用的就是android.intent.action.MAIN。android.intent.action.MAIN表示一个应用程序的入口,通常和android.intent.category.LAUNCHER联合使用。
3)data
data表示Intent携带的数据,通常和MIME类型联合使用。
4)category
category表示Intent的策略,目前常用的几个Category:android.intent.category.DEFAULT、android.intent.category.LAUNCHER、android.intent.category.MONKEY、android.intent.category.OPENABLE、android.intent.category.BROWSABLE。
对于隐式Intent,如果创建Intent时没有指明category属性,则系统会默认设置其属性为android.intent.category.DEFAULT,这时如果在Intent过滤器中没有指明category属性为android.intent.category.DEFAULT,则会造成匹配失败。
5)Extras
Extras表示Intent的附加信息,它在组件间传递消息时非常有用。目前Extras可以支持多种数据类型,如布尔型、整形、字符串等。
6)Flags
Flags表示Intent的标志位,经常用于Activity的场景中。Flags和Activity的启动模式有密切的关系。
(3)特殊应用场景
作为整个系统的灵魂组件,Intent功能之强大和使用范围之广,下面介绍Intent应用的一些特殊场景,如开启自启动、网络监视、获取内容、SD挂载等。
1)开机自启动
接收开机自启动事件的Intent过滤器的设置方法如下。
<receiver android:name=".receiver.ImServiceAutoStarter" android:process="android.process.im">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
2)网络监听
在基于网络的应用已非常普及的今天,监听网络的状态变化已是一种必备的功能,其Intent过滤器的设置方法如下。
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<intent-filter>
3)获取内容
为了响应获取内容的事件,必须在Intent过滤器中设置action属性为android.intent.action.GET_CONTENT,设置category属性为android.intent.category.DEFAULT.
4)返回桌面
为了返回桌面,需要设置category属性为Intent.CATEGORY_HOME
(4)Intent的分类
从目的地(ComponentName)的明确性来划分,Intent分显式Intent和隐式Intent。
所谓显式Intent,即明确指明了目的地、不需要系统进行Intent匹配的Intent,在应用程序内部进行组件调用时,应首选显式Intent。
所谓隐式Intent,即没有明确指定目的地、需要系统根据自己的信息进行匹配的Intent。这类Intent同样用于应用间的相互调用,有助于降低应用间的耦合性。
PendingIntent仅是对Intent的一个封装,它使开发者能够更方便地操作Activity、服务、广播等。
(5)PendingIntent的逻辑
PendingIntent和Intent略有不同,其可设定执行次数,主要用于远程服务通信、闹钟、通知、短信、启动器中国,一般的应用很少采用。
1)PendingIntent标志位
FLAG_ONE_SHOT表示返回的PendingIntent仅能执行一次,执行完成后即自动取消。
FLAG_NO_CREATE表示如果描述的PendingIntent不存在,并不创建相应的PendingIntent,而是返回NULL。
FLAG_CANCEL_CURRENT表示如果相应的PendingIntent已经存在,则取消前者,然后创建新的PendingIntent,者有利于保持数据为最新的,可用于即时通讯的通知场景。
FLAG_UPDATE_CURRENT表示更新PengdingIntent。
6.应用框架解析
除了基本的组件外,为了维护整个UI系统的良好运行,在应用层,Android还设计了诸多的框架来进行相关方面的管理。本机主要介绍Service框架、Activity管理机制、Broadcast机制、对话框框架、标题栏框架、状态栏框架、通知机制和ActionBar框架等。
(1)Service框架
作为执行应用后台运算和框架层运算的基本组件,服务扮演着十分重要的角色。根据通信的方式和应用场景,服务有不同的类型,具体而言,从通信的方式来看,服务科分为两种类型,即本地服务和远程服务,其中远程服务根据通信的方式又可分为基本AIDL的服务和基于Message的服务两种。从应用的场景来看,服务可以分为应用服务和系统服务等。
(2)Activity管理机制
Android的管理是通过Activity栈和Task来进行的。
1)Activity栈
Android的管理主要是通过Activity栈来进行的。当一个Activity启动时,系统根据其配置或调用的方式,将Activity压入一个特定的栈中,系统处于运行(Running or Resumed)状态。当按Back键或触发finish方法时,Activity会从栈中被压出,进而被销毁,当有新的Activity压入栈时,如果原Activity依然可见,则原Activity的状态将转变为暂停(Paused)状态,如果原Activity完全被遮挡,那么其状态将转变为停止(Stoped)。
2)Task
一个Task对应于一个Activity栈,Task是根据用户体验组成的运行期逻辑单元,Task中的Activity可以由不同的应用组成。
在实际的终端使用中,在主界面长按Home键弹出的一个网格界面即时当前运行的Task而非应用。
android:allowTaskReparenting属性用来配置是否允许Activity从启动它的Task移动到该Activity设置的Task亲和性相同的Task中。
android:alwaysRetainTaskState属性用于配置是否保留Activity所在的Task状态,默认为false。
android:clearTaskOnLaunch属性用于配置当Task从主界面重新启动时,是否需要清除除根Activity外的所有Activity,默认为false。
android:finishOnTaskLaunch属性用于配置当Task从主界面重新启动时,特定的Activity是否需要被销毁,默认为false。
android:taskAffinity属性用于配置启动Activity时运行在特定的Task中。只有在启动Activity的时候设置FLAG_ACTIVITY_NEW_TASK标志位才有效。
3)Activity生命周期
onResume()方法和很多初学者所认为的不同,其除了在Activity恢复可见性时被调用外,在构建Activity后也会被调用。另外,应避免直接调用onDestroy销毁Activity,争取销毁Activity的方式是调用finish方法。
(3)Broadcast机制
当特定时间发生时,需要通知到相应的模块,若受众不明确或较多,则需要进行广播。广播涉及顺序广播、无序广播、广播接收器。
1)顺序广播
当广播需要以类似消息链的方式进行时,应采用顺序广播,顺序广播的接收器可以抛弃或继续传递消息。
2)无序广播
无序广播是异步的,广播接收器除了接收广播外,无法对无序广播的行为产生影响。
3)广播接收器
为了接收广播,开发者必须在AndroidMainfest.xml中配置广播接收器或通过Java实现广播接收器。
(4)对话框框架
目前提供了4中方式来创建对话框,分别为AlertDialog、ProgressDialog、DataPickerDialog、TimePickerDialog。其中AlertDialog是最通用的对话框形式,ProcessDialog用于描述进度信息,而DataPickerDialog和TimePickerDialog则主要用于日期和时间场景中。
1)AlertDialog对话框
AlertDialog是最常用的对话框,由标题、图标、按钮和呈现具体信息的视图组成,在默认情况下,通常setMessage可以设置显示的文本信息,通过setView可以加载开发自定义的视图。
如果希望创建一个对话框,则需通过AlertDialog.Builder进行。在onCreateDialog中创建对话框,通过showDialog显示对话框。通过dismissDialog隐藏对话框,如果尚没有显示对话框,调用dismissDialog会发生异常。
通过调用setCancelable可以使弹出不希望被用户取消的对话框,适用于所有对话框。
由于Dialog管理机制的问题,Dialog具备记忆能力,在需要数据更新的场景中,在onPrepareDialog方法进行数据更新。
由于无法在对话框中记忆对话框状态,dismissDialog方法必须和showDialog成对出现,若无showDialog与之配对,则会发生异常。
2)ProgressDialog对话框
ProgressDialog通常用于耗时的操作,以免长时间无反应给用户造成一种系统假死的假象。
对于长时间运算的任务,应将ProgressDialog放在主线程之外执行,否则极易出现Android ANR消息。
ProgressDialog支持两种风格的进度显示,一种是进度条,一种是环形转动。这两种进度显示对应的风格分别为ProgressDialog.STYLE_HORIZONTAL和ProgessDialog.STYLE_SPINNER。默认的风格为ProgressDialog.STYLE_SPINNER。
3)DatePickerDialog对话框
DatePickerDialog(日期对话框)时一个专用的对话框,其创建方式非常简单,在创建时,通常需要设置初始年、月、日和监控日期变化的回调函数。
4)TimePickerDialog对话框
TimePickerDialog(时间对话框)和DatePickerDialog相似,TimePickerDialog在创建时需要设置初始时间和监控时间变化的回调函数。
(5)标题栏框架
Android中的标题栏具有传统标题栏更丰富的功能,其除了可标识当前界面的主题外,还支持进度显示,允许用户隐藏、自定义标题栏。目前Android标题栏支持FEATURE_NO_TITLE、FEATURE_PROGRESS、FEATRUE_CUSTOM_TITLE等多种定制。
1)隐藏标题栏
通过配置AndroidManifest.xml隐藏标题栏的方法:<activityandroid:name-"LunarLander" android:theme="@android:style/Theme.NoTitleBar">
通过代码实现隐藏标题栏的方法:requestWindowFeatrue(android.view.window.FEATURE_NO_TITLE)。
2)自定义标题栏
Android提供了自定义标题栏的方法,标题栏的FEATURE_CUSTOM_TITLE不能和FEATURE_LEFT_ICON、FEATURE_NO_TITLE等同时使用。
设置标题栏的方法:requestWindowFeature(window.FEATURE_CUSTOM_TITLE);getWindow().setFeatureInt(window.FEATURE_CUSTOM_TITLE,R.layout.custom_title_1);
3)进度显示
支持两种明确进度显示,一种是主进度,一种是辅进度,辅进度在本地应用中较少使用。在网络环境中,如在进行流媒体播放时,可以用主进度表示播放进度,用辅进度标识下载进度。
4)图标显示
Android的标题栏实际上由标题、进度条、左图标和右图标构成。
(6)状态栏框架
和传统终端的状态栏一样,Android状态栏同样提供了电量信息、蜂窝信息、SMS、MMS、邮件、WIFI信号、蓝牙信号、闹钟等状态信息。另外,状态栏还提供了应用安装、数据下载等职能终端特有的状态信息。除此之外,状态栏还承担着通知栏的功能,使用户能以最少的操作查看收到的信息。
在状态栏中,起主要作用的时StatusBarPolicy,它承担着接收系统发来的Intent消息、更新状态显示的功能,它是服务StatusBarMangerService的客户端。
整个状态栏框架是通过StatusBarService来实现的,在StatusBarService初始化时初始化了一个用于显示statusbar的StatusBarView。在StatusBarView中定义了状态栏的实现布局,而具体的布局文件时在framewoeks\base\packages\systemui\res\layout\status_bar.xml中实现的。
1)状态栏的隐藏
通过AndroidMainfest.xml设置全屏的方法:
<activity android:name="GActivity"
android:them="@android:style/Theme.Black.NoTitleBar.Fullscreen">
</activity>
通过Java设置全屏的方法:
getWindow().setFlags(WindowManger.LayoutParams.FLAG_FULLSCREEN,WindowManger.LayoutParames.FLAG_FUIISCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE); //隐藏标题栏
通过Java实现动态隐藏和显示状态栏
getWindow().addFlag(WindowManger.LayoutParame.FLAG_FULLSCREEN); //隐藏
getWindow().clearFlags(WindowManager,LayoutParame.FALG_FULLSCREEN); //显示
2)电量信息
当StatusBarPolicy收到Action为ACTION_BATTERY_CHANGED的Intent时,StatusBarPolicy会通知StatusBarManger进行电量图标的更新。
StatusBarPolicy还能相应Action为ACTION_BATTERY_LOW、ACTION_BATTERY_OKAY、ACTION_POWER_CONNECTED的Intent。
3)蜂窝信息
对蜂窝协议的支持十分充分,目前内置的支持包括GSM、UMTS、CDMA、4G等。
4)WIFI信号
对于WIFI信号,可以相应Action为WifiManger.NETWORK_STATE_CHANGED_ACTION、WifiManger.WIFI_STATE_CHANGED_ACTION、WifiManger.RSSI_CHANGED_ACTION的Intent。
5)蓝牙信号
对于蓝牙信号,Android目前可以相应BluetoothAdapter、BluetoothHeadset、BluetoothA2dp和BluetoothPbap的状态变化。
6)闹钟
当StatusBarPolicy收到Action为ACTION_ALERM_CHANGED的Intent时,StatusBarPolicy会通知StatusBarManager进行闹钟图标的更新。
(7)通知机制
Android提供了多种方式来向用户反馈状态信息,主要包括Toast提醒、通知栏提醒、对话框提醒等,其中Toast提醒通常用于页面的提示,通知栏提醒通常用于交互事件的通知,一般非常重要的提醒都已对话框的形式给出。
对于需要用户相应的事件,可以通过对话框的方式通知用户给予必要的反馈。
Toast和Notification均由框架层的NotificationManagerService维护。
1)Toast
Toast通常不用于交互,可以被创建于Activity和Service中,在默认情况下,Toast仅支持文本提示。
Toast提醒的显示时间较短。目前系统支持两种显示时间:LENGTH_SHORT和LENGTH_LONG。其中,LNEGTH_SHORT表示显示时间为2s,LENGTH_LONG表示显示时间为3.5s。
在默认情况下,Toast显示在屏幕的正下方,水平居中。对于特殊场景,Toast允许自定义显示的位置。
如果简单的文本信息无法满足开发者的需要,还可以利用Toast支持的自定义视图。
Toast不能再AsyncTask的doInBackground方法中运行,如果希望实现类似的效果,可以在Handler中进行处理。
2)Notifcation
Notifcation更适合于交互事件的通知,常用于短消息、即时消息、下载、外围设备的状态变化等场景中。
Notifcation支持文字显示、振动、三色灯、振铃音等多种提示形式,在默认情况下,Notifcation仅显示消息标题、消息内容、时间等3项内容。
1)Notification管理
Android通过表示符来管理Notification,发起一个Notification的方法:notificationManager.notify(notifictionId, mNotification);
取消Notification的方法很多,如果希望用户单击后Notification即被清除,则相应方法: notification.flags |= FALG_AUTO_CANCEL
如果希望手动清除某项Notification,相应方法:mNotificationMgr.cancel(LOW_MEMORY_MOTIFICATION_ID);
如果希望清除所有Notification时,相应方法:mNotification.cancelAll();
2)振动提醒
Android通过Notification还提供了振动提醒,通常用于比较紧迫的场景。
振动方式为:延迟0ms,然后振动700ms,在延迟500ms,接着振动1000ms。相应方法:Notification n=new Notification(); n.vibrate=new long[]{0, 700, 500, 1000}; mNM.notify(1, n);
如果设置为默认振动方法,相应方法: notification.defaults |= Notification.DEFAULT_VIBRATE。
3)三色灯提醒
Android支持三色灯提醒,开发者可以根据不同的场景选择点亮不同颜色的灯。需要注意的是,只要设置Notification的标志位为FLAG_SHOW_LIGHTS,才能支持三色灯提醒。
创建三色灯提醒的Notification:Notification n=new Notification(); n.flags |= Notification.FLAG_SHOW_LIGHTS; n.ledAREGB=0xff0000ff; n.ledOnMS = 300; n.ledOffMS = 300; mNM.notify(1,n);
如果希望设置默认三色灯提醒,相应方法:notification.defaults |= Notification.DEFAULT_LIGHTS;
4)振铃音提醒
Notification支持默认振铃音、自定义振铃音、Android多媒体数据库等多种提醒方法。
默认振铃音:notification.default |= Notification.DEFAULT_SOUND;
自定义振铃音:notification.sound=Uri.parse(file:///sdcard/notification/ringer.mps);
基于Android多媒体数据库提醒方式:notification.sound=Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
5)提醒标志位
FLAG_SHOW_LIGHTS //三色灯提醒
FLAG_ONGOING_EVENT //发起事件
FLAG_INSISTENT //振铃音将持续到Notification取消或Notification窗口打开
FLAG_ONLY_ALERT_ONCE //发起Notification后,振铃音或振动均执行一次
FLAG_AUTO_CANCEL //用户单击后自动消失
FLAG_NO_CLEAT //只有全部清除时,Notification才会清除
FLAG_FOREGROUND_SERVICE //表示正运行的服务
(8)搜索框架
通过框架层提供的搜索管理器(Search Manager),Android管理者搜索对话框并为用户传递搜索关键字。
实现搜索需要完成以下步骤:实现搜索配置文件,实现显示搜索结果的Activity,实现执行搜索的算法,发起搜索。
(9)ActionBar框架
ActionBar取代了状态栏和标题栏的位置,可以帮组开发者尽可能地利用空间。通过ActionBar还可以设置自定义的视图,即ActionView,其本质上是菜单的一种实现。
在ActionBar中,应用图标对单击事件的相应是通过onOptionsItemSelected方法进行的,其对应的ID为android.R.id.home。ActionBar通常需要和Fragment交互。
1)隐藏Actionbar
通过Androidmanifest.xml设置Activity的theme属性可以隐藏ActionBar,方法如下:
<activity android:theme="@android:style/Theme.Holo.NoActionBar">
当需要动态的隐藏ActionBar时,只能通过Java代码的方式实现,方法如下:
ActionBar actionBar=getActionBar();
actionBar.hide();
重新显示ActionBar的方法:
actionBar.show();
2)Action项管理
Action项本质上是一种特殊的菜单项,由图标和文字两部分组成,考虑到用户体验,在实际开发中,不建议设置超过2个的Action项。Action项有4种属性可以配置。
SHOW_AS_ACTION_ALWAYS //总是作为Action项显示
SHOW_AS_ACTION_IF_ROOM //空间足够时显示
SHOW_AS_ACTION_NEVER //永远不作为Action项显示
SHOW_AS_ACTION_WITH_TEXT //显示Action项的文字部分
3)ActionView
ActionView即所谓的在ActionBar上出现的Widget,用于实现一些快捷的操作,并充分利用ActionBar的空间。ActionView的实现由两种方式:加载布局文件和加载视图类。无论是加载布局文件还是加载视图类,均可通过配置文件实现。
4)添加Tab页
ActionBar可以显示Tab页,在Activity中进行Fragment间切换。每个Tab可以包含的元素有标题和图标,类似于TabWidget。向ActionBar中添加Tab页的步骤为:
创建ActionBar.TabListenter,并实现其方法。
设置ActionBar的导航模式为NAVIGATION_MODE_TABS.
创建Tab页。
添加Tab页。
在导航模式下Tab页的实现和TabActivity的实现有很大的区别,虽然两者切换Tab均是基于FrameLayout实现的,但前者需要开发者做更多的工作。
5)下拉菜单
基于ActionBar还能实现下拉菜单的功能。下拉菜单主要是基于SpinnerAdapter来处理数据的。实现下拉菜单的步骤如下:
设置导航模式。
实现并加载资源文件。
创建并设置OnNavigationListion。
7.Activity类控件
(1)ListActivity控件
1)ListActivity控件概述
ListActivity可以用来实现列表功能。在android中,ListActivity提供了对基本的单行、双行列表的封装,同时支持自定义列表。自定义列表主要是基于ListView来实现的,为了方便起见,在此一并介绍。
2)ListActivity控件实现步骤
实现一个列表包括3步:选择或自定义列表项布局文件、实现适配器并加载数据、为ListActivity设置适配器。
3)ListView布局文件
<ListView android:id="@+id/android:list" /> <TextView android:id="@+id/android:empty" android:text="no data" /> 当ListView没有数据显示时,TextView显示出来,同时ListView会被影藏(只有在ListActivity中才有此效果,在Activity中必须自行设置)。
基于单行布局的simple_list_item_1布局文件、基于简单双行布局的simple_list_item_2布局文件、基于单行单选布局的simple_list_item_single_choice布局文件、基于单行多选布局的simple_list_item_multiple_choice布局文件、类似树状图的simple_expandable_list_item_1/simple_expandable_list_item_2布局文件等。
(2)PreferenceActivity控件
1)PreferenceActivity控件概述
PreferenceActivity主要用于实现偏好设置,在布局上PreferenceActivity以PreferenceCreen为根布局,支持CheckBoxPreference等多种形式的偏好设置,这些偏好值默认存储于应用的SharePreference中,通过getSharedPreference可以获取SharedPreferences对象,通过Preference.OnPreferenceChangeListener监听器可以监听到偏好值得变化。
2)CheckBoxPreference控件
提供了进行二选一偏好的方法,还支持偏好的说明。
3)DialogPreference控件
DialgPreference仅作为一个借口存在,如果借助DialogPreference实现更加复杂的偏好必须继承DialogPreference。
4)EditTextPreference控件
提供支持输入框的偏好设置的功能,通过getEditText方法可以获得输入框的内容,通过getText方法可以获得SharedPreference中存储的偏好值,通过setText方法可以将偏好值保存在SharedPreferences中。
5)ListPreference控件
当某个偏好有多个偏好值可选时,ListPreference就派上用场了,在使用ListPreference是需要注意entries和entryValue属性,其中entries表示界面的内容,而entryValue对应的是实际偏好值。
6)RingtonePreference控件
用于设置铃声的特殊偏好控件,目前Android提供的铃声类型包括ringtong、notification、alarm和all等。其中all表示所有可用的铃声。
7)PreferenceCategory控件
提供了偏好组的功能。
3)TabActivity控件
1)TabActivity控件概述
能够让用户在单一界面实现更多的功能,简化用户的操作。
TabActivity的根布局控件为TabHost,他由TabWidget和通常基于FrameLayout的内容显示区域组成。
8.适配器
(1)适配器类型
目前Android支持两种类型的适配器:基本适配器(BaseAdapter)和游标适配器(CursorAdapter)。基本适配器是最通用的适配器,游标适配器是用来适配数据库的数据流的,其他的系统级适配器都是继承自这两种适配器。
(2)BaseAdapter适配器
BaseAdapter适配器是基本的适配器,是其他适配器的基类。实际开发中会调用BaseAdapter的子类或通过BaseAdapter自定义适配器来实现视图与数据的适配功能。
(3)ArrayAdapter适配器
在默认情况下,ArrayAdapter假定整个布局文件为一个TextView,只有指定了mFiledId,ArrayAdapter才认为加载了一个自定义布局。ArrayAdapter的实现有很强的局限性,仅能显示单行的列表。
(4)SimpleCursorAdapter适配器
在SimpleCursorAdapter的初始化和setViewBinder的实现过程中指定了布局文件、游标、数据项、控件ID等,但是没有处理布局加载和数据绑定,在bindView的实现中处理了布局加载和数据绑定。
从bindView的实现中可以看出,ViewBinder实际上是用户的一个自定义实现接口,当用户没有进行自定义实现时,会通过传递的控件数量进行默认数据绑定。
支持图片加载,不过这时通过游标获取的不再是文本数据,而是图片的URL。
在进行普通数据库数据加载时比较复杂的场景也可以利用SimpleCursorAdapter而非自定义适配器来实现。当默认数据绑定无法满足需求时,可以使用ViewBinder。
(5)适配器处理流程
在BaseAdapter适配器中,应用了设计模式的观察者模式(Observer Pattern),当数据源发生变化时,可以通知显示控件自行刷新。
通过分析,AdapterDataSetObserver是AdapterView的一个私有类,在开发者为ListView设置适配器时,ListView会通过适配器注册观察器,当开发者调用适配器的notifyDataSetChanged方法时,ListView会收到数据源变化的通知,进行自行刷新。
在数据库适配器中数据发生变化时,应重新获取游标(Cursor),然后在调用notifyDataSetChanged方法进行数据刷新。
(6)自定义适配器
1)基于BaseAdapter的自定义适配器
对于基于BaseAdapter的自定义适配器,需要重点关注getView=方法的实现,getView方法完成的主要工作是列表项布局文件的加载和数据的绑定。需要注意的是,只有convertView为空时加载布局文件,这样可以避免无谓的性能损耗,这是优化ListView显示的一个重要方法。
2)基于CursorAdapter的自定义适配器
基于CursorAdapter的自定义适配器的实现重点在于bingView方法和newView方法。其中bingView方法用于绑定数据,newView方法用于加载布局文件。
考虑到加载列表项时多次操作findViewById方法,对性能有所影响,因此在Android中设计ViewHolder,以其来进行优化。通过View的setTag方法和getTag方法可大幅度提高显示速率,这样是优化ListView显示的一种重要方法。
9.Service类组件
(1)InputMethodService
提供输入法的标准实现普通开发者不必关心这一点。一种输入法的界面由3部分组成,即软输入视图(Soft Input View)、候选视图(Candidates View)和全屏模式(Fullscreen Mode)。
(2)IntentService
IntentService作为Service的子类,主要用于处理异步请求,防止服务阻塞。所有的请求将在一个工作线程(HandleThread)中处理,工作结束后,xianc也结束。
(3)MediaScannerService
MediaScannerService主要在设备启动和SD卡挂载时执行多媒体文件的扫描工作。出于性能方面的考虑,Android区分SD卡和手机存储空间。
对于SD卡,会在收到Action为ACTION_MEDIA_MOUNTED的Intent(即SD卡挂载)时进行扫描。
对于手机存储空间,会在收到Action为ACTION_BOOT_COMPLETED的Intent(即设备启动完毕)时进行烧苗。另外在下载文件时,也可能启动媒体扫描服务。
(4)RecognitionService
RecognitionService是一个抽象服务,仅在开发者希望实现一个新的语音识别器时才可能用到。