1、让IT教学更简单,让IT学习更有效Android程序设计教程第5章 意图与广播目录 5.1 Intent意图 5.1.1 Intent原理及分类 5.1.2 Intent属性 5.1.3 Intent启动Activity 5.1.4 Intent Filter过滤器 5.2 BroadcastReceiver 5.2.1广播接收机制 5.2.2 使用BroadcastReceiver 5.3 Handler消息传递机制 5.3.1 Handler简介 5.3.2 Handler的工作机制 5.4 AsyncTask类学习目标 了解Intent原理及使用 掌握Intent的启动和数据传递 能够使
2、用BroadcastReceiver消息广播机制 能够使用Handler进行消息传递 能够使用AsyncTask异步处理机制5.1 Intent意图 Intent是Android系统应用内不同组件之间的通信载体,当在Android应用中连接不同的组件时,通常需要借助于Intent来实现。使用Intent可以激活Android的三个核心组件:Activity、Service和BroadcastReceiver。5.1.1 Intent原理及分类 Android使用Intent来封装程序的“调用意图”,无论是启动一个Activity组件还是Service组件,Android都使用统一的Intent
3、对象来封装这种“启动意图”,从而实现Activity、Service和BroadcastReceiver之间的通信。使用Intent启动Activity、Service和BroadcastReceiver三大组件所使用的机制略有不同:(1)当启动Activity组件时,通常需要调用startActivity(Intent intent)或startActivityForResult(Intent intent,int requestCode)方法,其中Intent参数用于封装目标Activity所需信息。(2)当启动Service组件时,通常需要调用startService(Intent in
4、tent)或bindService(Intent intent,ServiceConnection,int flags)方法,其中Intent参数用于封装目标Service所需信息。(3)当触发BroadcastReceiver组件时,通常调用sendBroadcast(Intent intent)等方法来发送广播消息,其中Intent参数用于封装目标BroadcastReceiver所需信息。根据Intent所描述的信息,可以将Intent意图分为以下两类:(1)显式Intent,明确指定需要启动或触发组件的类名,Android系统无须对该Intent做任何解析,系统直接找到指定的目标组件,
5、然后启动该组件即可。(2)隐式Intent,只指定需要启动或触发组件应满足的条件,Android系统需要对Intent进行解析,并得到启动组件所需要的条件,然后在系统中查找与之匹配的目标组件,如果找到符合该条件的组件,就启动相应的目标组件。5.1.2 Intent属性 Intent对象其实就是一个信息的捆绑包,是由Component(组件)、Action(动作)、Data(数据)、Category(类别)、Type(数据类型)、Extras(附加信息)和Flags(标志位)等属性组成 Component组件为目标组件,需要接收一个ComponentName对象,而ComponentName对象
6、的构造方法有以下几种方式。ComponentName(String pkg,String className):用于创建pkg包下的className所对应的组件;其中参数pkg代表应用程序的包名,参数className代表组件的类名。ComponentName(Context context,String className):用于创建context上下文中className所对应的组件。ComponentName(Context context,Class className):用于创建context上下文中className所对应的组件。Action是一个字符串,用于描述一个Androi
7、d应用程序的组件。一个Intent Filter中可以包含一个或多个Action,当在AndroidManifest.xml中定义Activity时,在节点中指定一个Action列表用于标识Action所能接收的动作 Category属性用来描述动作的类别,在元素中进行声明,Intent类中提供了标准的Category常量及对应的字符串 Data属性通常与Action属性结合使用,为Intent提供可操作的数据。Data属性接收一个URI对象 Type属性用于指定Data属性URI所对应的MIME类型,该类型可以是自定义的MIME类型,也可以是系统自带的MIME类型,只要符合特定格式的字符串即
8、可,例如:text/html。Data属性与Type属性的关系比较微妙,两个属性之间能够相互覆盖,例如:(1)如果为Intent先设置Data属性,再设置Type属性,那么,Type属性将会覆盖Data属性。(2)如果为Intent先设置Type属性,再设置Data属性,那么,Data属性将会覆盖Type属性。(3)如果希望Intent既有Data属性又有Type属性,应该调用Intent的setDataAndType()方法。Extras属性是一个Bundle对象,通常用于在多个Activity之间交换数据。其中Bundle与Map非常类似,可以存入多组键值对,在Intent中通过Bundl
9、e类型的Extras属性来封装数据,从而实现组件之间的数据传递。Extras属性的使用过程如下代码所示。Intent intent=new Intent(MainActivity.this,SecondActivity.class);Bundle bundle=new Bundle();bundle.putString(name,重庆机电);intent.putExtras(bundle);startActivity(intent);Flags属性用于为Intent添加一些额外的控制标志,通过Intent的addFlags()方法为Intent添加控制标志。5.1.3 Intent启动Acti
10、vity 通过调用Context的startActivity()方法可以创建并显示目标Activity,该方法需要传入一个Intent类型的参数,代码如下所示:startActivity(intent);Intent来显式地指定要打开的Activity,即使用Intent对象来指定要打开的Activity的类名,然后调用startActivity()方法启动Activity。例如:Intent intent=new Intent(MainActivity.this,SecondActivity.class);startActivity(intent);隐式Intent提供了一种机制,可以使匿名
11、的应用程序组件响应动作请求。当系统启动一个可执行给定动作的Activity时,而不需要指明所要启动的某个应用程序中具体的Activity。例如,当用户在应用程序中拨打电话时,可以使用一个隐式的Intent来请求执行,代码如下所示。Intent intent=new Intent(Intent.ACTION_DIAL,Uri.parse(tel:10000);startActivity(intent);常见的使用Intent来启动内置应用程序有以下四种:1)启动浏览器在Activity启动内置浏览器时,需要创建一个使用ACTION_VIEW Action,URI为URL网址的Intent对象。代
12、码如下所示。Intent intent=new Intent(Intent.ACTION_VIEW,Uri.parse(http:/);startActivity(intent);2)启动地图启动内置Google地图时,也是使用ACTION_VIEW Action,URI为GPS坐标值。代码如下所示。Intent intent=new Intent(Intent.ACTION_VIEW,Uri.parse(geo:25.0456879,121.23456);startActivity(intent);3)打电话启动拨号器程序时,使用ACTION_VIEW Action,URI为电话号码。代码如
13、下所示。Intent intent=new Intent(Intent.ACTION_DIAL,Uri.parse(tel:10000);startActivity(intent);4)发送电子邮件在Activity中可以启动内置电子邮件工具来发送邮件,使用ACTION_SENDTO Action,URI为收件人的电子邮件地址。代码如下所示。Intent intent=new Intent(Intent.ACTION_SENDTO,Uri.parse(mailto:);startActivity(intent);Activity之间的传递数据通过Intent的putExtra()或putExt
14、ras()方法可以向目标Activity传递数据。其中,putExtras()方法用于向Intent中批量添加数据。此时,通常先将数据批量添加到Bundle对象中,然后再调用Intent的putExtras()方法直接传递该Bundle对象即可。示例代码如下所示。Intent intent=new Intent(MainActivity.this,SecondActivity.class);Bundle bundle=new Bundle();bundle.putString(name,重庆机电职业技术学院);bundle.putString(address,重庆市璧山区璧青路);intent
15、.putExtras(bundle);startActivity(intent);使用putExtra()方法也可以向Intent中添加数据,但该方法需要将数据一个一个第添加到Intent中,示例代码如下所示。Intent intent=new Intent(MainActivity.this,SecondActivity.class);intent.putExtra(name,重庆机电职业技术学院);intent.putExtra(address,重庆市璧山区璧青路);startActivity(intent);4.从Activity返回数据 通过startActivity()方法新启动的A
16、ctivity与原Activity是相互独立的,在关闭时不会返回任何信息。当需要返回数据时,可以使用startActivityForResult()方法启动一个Activity,新启动的Activity在关闭时可以向原Activity返回数据。与其他Activity一样,新启动的Activity也必须在AndroidManifest.xml文件中注册,被注册的任何Activity都可以用作目标Activity,包括系统Activity或第三方应用程序Activity。当目标Activity结束时,会触发Activity的onActivityResult()事件处理方法来返回结果。startAc
17、tivityForResult()方法特别适合于从一个Activity向另一个Activity提供数据输入的情况,如登录注册等功能。1)启动一个目标ActivitystartActivityForResult()方法需要传入Intent参数,用于显式或隐式决定启动哪个Activity,除此之外,还需要传入一个请求码,用于唯一标识返回结果的目标Activity。2)从目标Activity中返回数据在目标Activity中调用finish()方法之前,通过setResult()方法向原Activity返回一个结果。setResult()方法是一个重载方法,3)处理从目标Activity返回的数据当
18、目标Activity关闭时,触发并调用Activity的onActivityResult()事件处理方法。通过重写onActivityResult()方法来处理从目标Activity返回的结果5.1.4 Intent Filter过滤器 Intent Filter表示意图的过滤器,用于描述指定的组件可以处理哪些意图。对于Activity、Service和BroadcastReceiver,只有设置了Intent Filter,才能被隐式Intent调用。当应用程序安装时,Android系统会解析每个组件的Intent Filter,从而确定这些组件可以处理哪些Intent。当有Intent发生
19、时,Android根据Intent Filter的配置信息,从中找到可以处理该Intent的组件。在Intent Filter中可以包含Intent对象的ACTION、DATA和CATEGORY这三个属性。隐式Intent必须通过这三个属性测试才能传递到所匹配的组件中。当需要组件支持隐式Intent时,必须在AndroidManifest.xml中配置元素。5.2 BroadcastReceiver BroadcastReceiver是广播接收器,用于接收系统和应用中的广播。在应用程序之间,广播是一种广泛运用的传输信息的机制。BroadcastReceiver是一种对广播进行过滤接收并响应的组
20、件,该组件本质上就是一个全局监听器,用于监听系统全局的广播消息。5.2.1广播接收机制 事件处理机制类似,实现广播和接收Intent的步骤如下:(1)定义BroadcastReceiver广播接收器。创建一个BroadcastReceiver的子类,并重写onReceive()方法,该方法是广播接收处理方法,在接收到广播后进行相应的逻辑处理。(2)注册BroadcastReceiver广播接收器。用于接收消息并对该消息进行响应。(3)发送广播。该过程将消息内容和用于过滤的信息封装起来,并进行广播。(4)执行。满足过滤条件的广播接收器接收广播信息,并执行onReceive()方法。(5)销毁。广
21、播接收器不使用时将被销毁。5.2.2 使用BroadcastReceiver 使用BroadcastReceiver的实现步骤如下:(1)定义一个BroadcastReceiver的子类,并重写onReceive()方法,在接收到广播后进行相应的逻辑处理。(2)在AndroidManifest.xml文件中注册广播接收器对象,并指明触发BroadcastReceiver事件的条件。(3)在AndroidManifest.xml中添加相应的权限。5.3 Handler消息传递机制 Handler类位于android.os包下,主要的功能是完成Activity的Widget与应用程序中线程之间的交
22、互。使用Handler可以在一个线程中发出消息,在另一个线程中接收消息并进行处理。Handler类中包含发送、接收和处理消息的方法 开发带有Handler类的程序步骤如下。(1)在Activity或Activity的Widget中开发Handler类的对象,并重写handleMessage方法。(2)在新启动的线程中调用sendEmptyMessage或者sendMessage方法向Handler发送消息。(3)Handler类的对象用handleMessage方法接收消息,然后根据消息的不同执行不同的操作。5.3.2 Handler的工作机制 配合Handler工作的其他组件:(1)andr
23、oid.os.Message用于封装线程之间传递的消息。(2)android.os.MessageQueue消息队列,用于负责接收并处理Handler发送过来的消息。(3)android.os.Looper每个线程对应一个Looper,负责消息队列的管理,将消息从队列中取出交给Handler进行处理。Looper类中主要包含prepare()和loop()两个静态方法。(1)Looper.prepare():在线程中保存一个Looper实例,其中保存一个MessageQueue对象。Looper.prepare()方法在每个线程中只能调用一次,否则会抛出异常。因此,在一个线程中只会存在一个Me
24、ssageQueue。(2)Looper.loop():当前线程通过无限循环的方式,不断从MessageQueue队列中读取消息,然后回调Message.target.dispatchMessage(msg)方法将消息分配给Handler对象并进行处理。其中,Message的target属性为所关联的Handler对象。5.4 AsyncTask类 Android系统的Handler机制为多线程异步消息处理提供了一种完善的处理方式,但是在较为简单的情况下,使用Handler方式会使代码过于繁琐。为了简化操作,Android系统提供了android.os.AsyncTask工具类,使得异步任务的
25、处理变得更加简单,不再需要编写任务线程和Handler实例也可以完成相同的任务。定义AsyncTask的语法格式如下:public abstract class AsyncTask 其中,Params是启动任务执行的输入参数;Progress是后台任务执行的进度;Result是后台计算结果的类型。在执行异步任务时,通常会涉及以下几个步骤:(1)execute(Params.params):用于执行一个异步任务,需要在业务代码中调用该方法,来触发异步任务的执行。(2)onPreExecute():在execute()方法被调用后立即执行,在后台任务执行之前对UI做一些标记。(3)doInBack
26、ground(Params.params):在onPreExecute()方法完成之后立即执行,用于执行较为费时的操作。此方法将接收输入参数并返回计算结果。在执行过程中可以调用publishProgress()方法来更新进度信息。(4)onProgressUpdate(Progress.values):在调用publishProgress()方法时,自动执行onProgressUpdate()方法将进度信息直接更新到UI组件上。(5)onPostExecute(Result result):当后台操作结束时调用该方法,并将计算结果作为输入参数传递到方法中,然后将结果显示到UI组件上。在使用AsyncTask工具类时,需要特别注意以下几点:(1)异步任务的实例必须在UI线程中创建.(2)execute(Params.params)方法必须在UI线程中调用。(3)不能手动调用onPreExecute()、doInBackground(Params.params)、onProgressUpdate(Progress.values)和onPostExecute(Result result)等方法。(4)不能在doInBackground(Params.params)方法中更改UI组件的信息。(5)每个任务实例只能执行一次,当执行第二次时将会抛出异常。谢谢