260 likes | 410 Views
第二章 Android 应用程序. 本章学习目标:. 了解 Android 基本组件 了解 Android 生命周期 掌握 Android 程序调试. 2.1 基本组件介绍.
E N D
本章学习目标: • 了解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访问共享资源时,需要为应用程序添加适当的权限才可以。权限为“<uses-permission.android:name=”android.permission.READ_CONTACTS”/>”。
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生命周期 • 图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生命周期的事件回调函数表
2.2 Activity生命周期 • 除了Activity生命周期的事件回调函数以外,还有onRestoreInstanceState()和onSaveInstanceState()两个函数经常会被使用,用于保存和恢复Activity的状态信息,例如用户在界面中选择的内容或输入的数据等。这两个函数不是生命周期的事件回调函数,不会因为Activity的状态变化而被调用,但在下述情况下会被调用:Android系统因为资源紧张需要终止某个Activity,但这个Activity在未来的某一时刻还会显示在屏幕上。 • 表2-2 Activity状态保存/恢复的事件回调函数说明表
2.2 Activity生命周期 • 图2-3 Activity事件回调函数的调用顺序图
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区域内。