第二章Android应用程序
Download
Report
Transcript 第二章Android应用程序
第二章 Android应用程序
本章学习目标:
了解Android基本组件
了解Android生命周期
掌握Android程序调试
2.1 基本组件介绍
Android应用程序由组件组成,组件是可以被调
用的基本功能模块。Android系统利用组件实现
程序内部或程序间的模块调用,以解决代码复用
的问题,这是Android系统非常重要的特性。在
程序设计时,在AndroidManifest.xml中声明可
共享的组件,声明后其他应用程序可以直接调用
这些共享组件。Android系统有4个重要的组件,
分别是Activity、Service、
BroadcaseReceiver和ContentProvider。
2.1 基本组件介绍
Activity是Android中最常用的组件,是应用程序的表示层,
Activity一般通过View来实现应用程序的用户界面,相当与一个
屏幕,用户与程序的交互是通过该类实现的。Android应用程序
可以包含一个或多个Activity,一般在程序启动后会呈现一个
Activity,用于提示用户程序已经正常启动。Activity在界面上的
表现形式一般是全体窗体,也可以是非全屏悬浮窗体或对话框。
Service一般用于没有用户界面,但需要长时间在后台运行的应用。
实际上,Service是一个具有较长的生命周期但是并没有用户界面
的程序。例如在播放MP3音乐时,使用Service播放MP3音乐,可
以在关闭播放器界面的情况下长时间播放MP3音乐,并通过对外
公开Service的通信接口,控制MP3音乐播放的启动、暂停和停止。
2.1 基本组件介绍
Service一般由Activity启动,但是并不依赖于Activity,即当
Activity的生命周期结束时,Service仍然会继续运行,直到自己
的生命周期结束为止。Service的启动方式有两种。startService
方式启动是当Activity调用startService方法启动Service时,会
依次调用onCreate和onStart方法来启动Service,而当调用
stopService方法结束Service时,又会调用onDestroy方法结束
Service。Service同样可以在自身调用stopSelf或stopService
方法来结束Service。bindService 方式启动是Activity调用
bindService方法启动Service,此时会依次调用onCreate和
onBind方法启动Service。而当通过unbindService方法结束
Service时,则会依次调用onUnbind和onDestroy方法。
2.1 基本组件介绍
BroadcastReceiver为用户接收广播通知的组件,当系统或某个
应用程序发送广播时,可以使用BroadcastReceiver组件来接收
广播信息并做相应处理。在信息发送时,需要将信息封装后添加
到一个Intent对象中,然后通过调用Content.sendBroadcast()、
sendOrderedBroadcast()或sendStickyBroadcast()方法将
Intent对象广播出去,然后接收者会检查注册的IntentFilter是否
与收到的Intent相同,当相同时便会调用onReceive()方法来接
收信息。三个发送方法的不同之处是使用sendBroadcast()或者
sendStickyBroadcast()方法发送广播时,所有满足条件的接收
者会随时地执行,而使用sendOrderedBroadcast()方法发送的
广播接受者会根据IntentFilter中设置的优先级顺序来执行。
2.1 基本组件介绍
BroadcastReceiver的使用过程如下:
1、将需要广播的消息封装到Intent中。
2、然后通过三种发送方法中的一种将Intent广播出去。
3、通过IntentFilter对象来过滤所发送的实体Intent。
4、实现一个重写了onReceive方法的BroadcastReceiver。
需要注意的是,注册BroadcastReceiver对象的方式有两种,一
种是在AndroidManifest.xml中声明,另一种是在Java代码中设
置。在AndroidManifest.xml中声明时,将注册的信息包裹在
<receiver></receiver>标签中,并通过<intent-filter>标签
来设置过滤条件;在Java代码中设置时,需要先创建IntentFilter
对象,并为IntentFilter对象设置Intent的过滤条件,并通过
Content.registerReceiver方法来注册监听,然后通过
Content.unregisterReceiver方法来取消监听
2.1 基本组件介绍
ContentProvider是用来实现应用程序之间数据共享的类。当需要进
行数据共享时,一般利用ContentProvider为需要共享的数据定义一
个URI,然后其他应用程序通过Content获得ContentResolver并将数
据的URI传入即可。Android系统已经为一些常用的数据创建了
ContentProvider,这些ContentProvider都位于android.provider
下,只要有相应的权限,自己开发的应用程序便可以轻松地访问这些数
据。
对于ContentProvider最重要的就是数据模型(data model)和URI,
接下来分别对其进行介绍。数据模型就是ContentProvider为所有需
要共享的数据创建一个数据表,在表中,每一行表示一条记录,而每一
列代表某个数据,并且其中每一条数据记录都包含一个名为“_ID”的
字段类标识每条数据。URI就是每个ContentProvider都会对外提供一
个公开的URI来标识自己的数据集,当管理多个数据集时,将会为每个
数据集分配一个独立的URI,所有的URI都以“content://”开头。需
要注意的是,使用ContentProvider访问共享资源时,需要为应用程
序添加适当的权限才可以。权限为“<usespermission.android:name=”android.permission.READ_CONTA
CTS”/>”。
2.2 Activity生命周期
Activity生命周期指Activity从启动到销毁的过程,在这个过程中,
Activity一般表现为4种状态,分别是活动状态、暂停状态、停止
状态和非活动状态。活动状态是指当Activity在用户界面中处于最
上层,用户完全看得到,能够与用户进行交互,则这时Activity处
于活动状态;暂停状态是指当Activity在界面上被部分遮挡,该
Activity不再处于用户界面的最上层,且不能够与用户进行交互,
则这个Activity处于暂停状态;停止状态是指Activity在界面上完
全不能被用户看到,也就是说这个Activity被其他Activity全部遮
挡,则这个Activity处于停止状态;非活动状态是指Activity所处
的不在以上三种状态中的另一种状态。
2.2 Activity生命周期
Activity启动后处于活动状态,此时的Activity处于最上层,是与
用户正在进行交互的组件,因此Android系统会努力保证处于活
动状态Activity的资源需求,资源紧张时可终止其他状态的
Activity;如果用户启动了新的Activity,部分遮挡了当前的
Activity,或新的Activity是半透明的,则当前的Activity转换为
暂停状态,Android系统仅在为处于活动状态的Activity释放资源
时才终止处于暂停状态的Activity;如果用户启动新的Activity完
全遮挡了当前的Activity,则当前的Activity转变为停止状态,停
止状态的Activity将优先被终止;活动状态的Activity被用户关闭
后,或暂停状态或停止状态的Activity被系统终止后,Activity便
进入了非活动状态。
2.2 Activity生命周期
活动状态
停止状态
暂停状态
图2-1 Activity状态变换图
非活动状态
2.2 Activity生命周期
为能够更好地理解Activity的生命周期,还需要对Activity栈做一
个简要的介绍。Activity栈保存了已经启动且没有终止的所有
Activity,并遵循“后进先出”的原则。如图2-2所示,栈顶的
Activity处于活动状态,除栈顶以外的其他Activity处于暂停状态
或停止状态,而被终止的Activity或已经出栈的Activity的则不在
栈内。
Activity的状态与其在Activity栈的位置有着密切的关系,不仅如
此,Android系统在资源不足时,也是通过Activity栈来选择哪些
Activity是可以被终止的。一般来讲,Android系统会优先选终止
处于停止状态,且位置靠近栈底的Activity,因为这些Activity启
动顺序最靠前,而且在界面上用户是看不到的。
2.2 Activity生命周期
Activity
入栈
活动状态
Activity
出栈
Activity
非活动状态
Activity
非活动状态
Activity
Activity
暂停状态
或
停止状态
.
.
.
.
.
.
Activity
终止
释放资源
Activity 栈
图2-2 Activity栈图
2.2 Activity生命周期
随着用户在界面的操作和Android系统对资源的管理,Android不断变
化在Activity栈的位置,其状态也不断在四种状态中转变。为了能够让
Android程序了解自身状态的变化,Android系统提供了多个事件回调
函数,在事件回调函数中添加相关代码,就可以在Activity状态变化时
完成适当的工作。下面的代码给出了Activity的主要事件回调函数。
public class MyActivity extends Activity {
protected void onCreate(Bundle savedInstanceState);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy(); }
2.2 Activity生命周期
表2-1 Activity生命周期的事件回调函数表
函数
是否
可终止
说明
onCreate()
否
Activity启动后第一个被调用的函数,常用来进行Activity的初始化,例如创建View、绑定数据或
恢复信息等。
onStart()
否
当Activity显示在屏幕上时,该函数被调用。
onRestart()
否
当Activity从停止状态进入活动状态前,调用该函数。
onResume()
否
当Activity能够与用户交互,接受用户输入时,该函数被调用。此时的Activity位于Activity栈的栈
顶。
onPause()
是
当Activity进入暂停状态时,该函数被调用。一般用来保存持久的数据或释放占用的资源。
onStop()
是
当Activity进入停止状态时,该函数被调用。
onDestroy()
是
在Activity被终止前,即进入非活动状态前,该函数被调用。
2.2 Activity生命周期
除了Activity生命周期的事件回调函数以外,还有
onRestoreInstanceState()和onSaveInstanceState()两个函
数经常会被使用,用于保存和恢复Activity的状态信息,例如用户
在界面中选择的内容或输入的数据等。这两个函数不是生命周期
的事件回调函数,不会因为Activity的状态变化而被调用,但在下
述情况下会被调用:Android系统因为资源紧张需要终止某个
Activity,但这个Activity在未来的某一时刻还会显示在屏幕上。
表2-2 Activity状态保存/恢复的事件回调函数说明表
函数
是否
可终止
说明
onSaveInstanceState()
否
Android系统因资源不足终止Activity前调用该函数,用以保存Activity的状态信息,
供onRestoreInstanceState()或onCreate()恢复之用。
onRestoreInstanceState()
否
恢复onSaveInstanceState()保存的Activity状态信息,在onStart()和onResume
()之间被调用。
2.2 Activity生命周期
1
onCrea
te
2
3
4
onSta
rt
onRestore
InstanceS
tate
onResum
e
5
onSave
InstanceS
tate
7
onPause
6
onRestar
t
活动生命周期
可视生命周期
全生命周期
图2-3 Activity事件回调函数的调用顺序图
8
onSto
p
9
onDestr
oy
2.2 Activity生命周期
全生命周期是从Activity建立到销毁的全部过程,始于onCreante(),结
束于onDestroy()。一般情况下,使用者在onCreate()中初始化
Activity所能使用的全局资源和状态,并在onDestroy()中释放这些资源。
例如,Activity中使用后台线程下载网络数据,则在onCreate()中创建
线程,在onDestroy()中停止并销毁线程。在一些极端的情况下,
Android系统会不调用onDestroy()函数,而直接终止进程。
可视化生命周期是Activity在界面上从可见到不可见的过程,开始于
onStart(),结束于onStop()。onStart()一般用来初始化或启动与更新
界面相关的资源。onStop()一般用来暂停或停止一切与更新用户界面相
关的线程、计时器和服务,因为在调用onStop()后,Activity对用户不
再可见,更新用户界面也就没有任何实际意义。onRestart()函数在
onStart()前被调用,用来在Activity从不可见变为可见的过程中,进行
一些特定的处理过程。因为Activity不断从可见变为不可见,再从不可见
变为可见,所以onStart()和onStop()会被多次调用。另外,onStart()
和onStop()也经常被用来注册和注销BroadcastReceive,例如使用者
可以在onStart()注册一个BroadcastReceive,用来监视某些重要的广
播信息,并使用这些消息更新用户界面中的相关内容,并可以在
onStop()中注销BroadcastReceive。
2.2 Activity生命周期
活动生命周期是Activity在屏幕的最上层,并能够与用户交互的阶段,
开始于onResume(),结束于onPause()。例如,在手机进入休眠状
态时,处于活动生命周期的Activity会调用onPause(),当手机从休眠
状态被唤醒后,则会调用onResume()。因为在Activity的状态变换过
程中onResume()和onPause()经常被调用,因此这两个函数中应使
用更为简单、高效的代码。
函数调用顺序为:onCreate() → onStart()→ onResume() →
onPause()→ onStop()→ onDestroy()。在Activity启动时,系统
首先调用调用onCreate()函数分配资源,然后调用onStart()将
Activity显示在屏幕上,之后调用onResume()获取屏幕焦点,使
Activity能接受用户的输入,这时用户能够正常使用这个Android程序
了。用户单击“回退键”或Activity调用finish()函数时,会导致
Activity关闭,系统会相继调用onPause()、onStop()和
onDestroy(),释放资源并销毁进程。因为Activity关闭后,除非用户
重新启动应用程序,否则这个Activity不会出现在屏幕上,因此系统直
接调用onDestroy()销毁了进程,且没有调用
onSaveInstanceState()函数来保存Activity状态。
2.2 Activity生命周期
从可视化生命周期的函数调用顺序为:onSaveInstanceState
()→ onPause()→ onStop() → onRestart()→ onStart()→
onResume()。Activity启动后,当内置的拨号程序被启动时,原
有的Activity被完全覆盖,系统首先调用onSaveInstanceState()
函数保存Activity状态,因为界面上不可见的Activity可能被系统
终止;系统然后调用onPause()和onStop(),停止对不可见
Activity的更新。在用户关闭拨号程序后,系统调用onRestart()
恢复需要界面上需要更新的信息,然后调用onStart()和
onResume()重新显示Activity,并接受用户交互。系统调用了
onSaveInstanceState ()保存Activity的状态,因为进程没有被
终止,所以没有调用onRestoreInstanceState()恢复保存的
Activity状态。
2.2 Activity生命周期
为了分析活动生命周期中的函数调用顺序,首先启动
ActivityLifeCycle,然后通过“挂断键”使模拟器进入休眠状态,
然后再通过“挂断键”唤醒模拟器。
活动生命周期中的函数调用顺序如下:onSaveInstanceState()
→ onPause() → onResume()。Activity进入休眠状态前,系
统首先调用onSaveInstanceState ()保存Activity的状态,然后
调用onPause()停止与用户交互;在系统被唤醒后,系统调用
onResume()恢复与用户的交互。
2.3 Android程序调试
LogCat是用来获取系统日志信息的工具,并可以显示在Eclipse
集成开发环境中。LogCat能够捕获的信息包括Dalvik虚拟机产生
的信息、进程信息、ActivityManager信息、
PackagerManager信息、Homeloader 信息、
WindowsManager信息、Android运行时信息和应用程序信息等
等。在Eclipse的默认开发模式下没有LogCat的显示页,用户可
以使用Window → Show View → Other打开Show View的选
择菜单,然后在Andoird → LogCat中选择LogCat。这样,
LogCat便会在Eclipse的下方区域显示出来。
2.3 Android程序调试
LogCat的右上方的5个字母[V]、[D]、[I]、[W]、[E],表示五
种不同的日志信息,分别是详细(Verbose)信息、调试
(Debug)信息、通告(Info)信息、警告(Warn)信息、错误
(Error)信息。不同类型日志信息的级别是不相同的,级别最高
的是错误信息,其次是警告信息,然后是通知信息和调试信息,
最后是详细信息。 在LogCat中,用户可以通过五个字母图标选择
显示的信息类型,级别高于所选类型的信息也会在LogCat中显示,
但级别低于所选类型的信息则不会被显示。
即使用户指定了所显日志信息的级别,仍然会产生很多日志信息,
很容易让用户不知所措。LogCat还提供了“过滤”功能,在右上角
的“+”号和“-”号,分别是添加和删除过滤器。用户可以根据日志
信息的标签(Tag)、产生日志的进程编号(Pid)或信息等级
(Level),对显示的日志内容进行过滤。
2.3 Android程序调试
在Android程序调试过程中,首先需要引入android.util.Log包,
然后使用Log.v()、 Log.d()、 Log.i() 、Log.w() 和 Log.e()
五个函数在程序中设置“日志点”。每当程序运行到“日志点”时,应
用程序的日志信息便被发送到LogCat中,使用者可以根据“日志
点”信息是否与预期的内容一致,判断程序是否存在错误。之所以
使用5个不同的函数产生日志,主要是为了区分日志信息的类型,
其中,Log.v()用来记录详细信息,Log.d()用来记录调试信息,
Log.i()用来记录通告信息, Log.w()用来记录警告信息,Log.e()
用来记录通错误信息。
2.3 Android程序调试
如果能够使用LogCat的过滤器,则可以使显示的结果更加清晰。
下面使用在LogCat右上角的“+”号,添加一个名为
LogcatFilter的过滤器,并设置过滤条件为“标签=LOGCAT”。
过滤器设置好后,LogcatFilter过滤后的日志信息如图2-11所示。
在这之后,无论什么类型的日志信息,属于哪一个进程,只要标
签为LOGCAT,都将显示在LogcatFilter区域内。
谢谢!