第二章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区域内。
谢谢!