Android应用中消息传递方法分析

2014-07-18 18:46史书明
电脑知识与技术 2014年13期
关键词:主线线程调用

摘要:一个Android应用中存在各种消息,这些消息在不同组件中生成,在Activity界面之间,Fragment之间以及多个线程间传递。程序员需要深入了解Android应用中消息产生的原理,并熟练掌握消息传递的不同方法,才能合理控制程序运行的方向,创作正确的Android手机端软件。

关键词:Android消息传递方法;Fragment;Intent;Handler

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2014)13-2984-03

Analysis of Messaging Methods in Android

SHI Shu-ming

(School of Computer Information & Engineering, Changzhou Institute of Technology, Changzhou 213002, China)

Abstract: There are lots of message in a Android application, these message are generated in different components, delivered between activities, fragments or threads. A programmer need to understand the principle of product message deeply, and become familiar with different messaging methods, in order to control direction of program running and create correct Android mobile software.

Key words: Messaging methods; Fragment; Intent; Handler

在移动互联网时代,移动终端的地位变得越来越重要,智能手机已成为人们日常生活中的必需品,基于移动设备操作系统的开发是现在程序开发的新方向。

根据Nielsen公司2013年6月的调查,智能机中53%为Android操作系统,领先于Apple IOS, BlackBerry以及Windows Phone等其他手机操作系统。作为程序开发人员,掌握Android平台下手机软件的开发技术是势在必行的。在Android开发中,掌握Android消息的处理方法,是从事Android开发的必备条件。

1 Android应用中的消息

一个Android应用中,在不同时机都会有大量的消息生成和传递,如图1所示。①父Activity界面可以向子Activity界面传送结果,同样子Activity也可以向父Activity传递用户的选择。②一个Activity中可以嵌入多个Fragment片断,Fragment接收用户的操作,并将操作结果在另一个Fragment中显示时,同样存在着数据的传换。③UI主线程在需要执行耗时任务时,通常会启动子线程完成工作,因此子线程与UI主线程之间必然需要信息的互通。

下文,将根据产生消息组件的类型不同,来说明组件间消息传递的方法。

图1 Android应用中消息的传递

2 消息传递方法

2.1 Activity间消息传递方法

一个Android应用,通常会有多个界面组成,这些界面即为Activity。在一个界面中调用另一个界面,这两个界面即存在父子关系。父界面要向子界面传递结果信息,或者子界面要向父界面反馈用户选择结果,这时在两个Activity之间负责传递消息的中介为Intent对象,如图2所示。

图2 Activity消息传递

父Activity中通过startActivity(Intent)方法通知Android操作系统要调用子Activity,并在Intent对象中放入要传递的数据。子Activity通常在其onCreate()方法中,获取Intent对象,并提取传递来的数据。

根据Android 参考文档(API level 19)中的解释,Intent类是将要执行动作的抽象描述,可以用其启动Activity,或与Service交互,或是向BroadcastReceiver组件发送消息。

Intent最重要的用途是启动Activities,一个Intent包含的重要信息有两块,即action和data。action是指动作的简要描述,如系统定义的“VIEW_ACTION”为查看;data用Uri的形式表示,描述要action要操作的数据,如“tel:123”,该Uri数据表示电话号码123。

Intent除了action和data这两个重要属性外,还有一个extras属性,可用于携带Bundle类型的额外数据,我们在Activity间传递的数据就是通过调用Intent对象的putExtras(Bundle)方法,放入这个属性中。下面的示例,将显示启动一个子Activity,并将当前的时间作为消息进行传送。

Intent intent=new Intent(FatherActivity.this, SonActivity.class);

/*准备Bundle数据*/

Bundle extras=new Bundle();

extras.putLong("date", SystemClock. elapsedRealtime());

/*向Intent的extras属性放入传递数据*/

intent.putExtras(extras);

startActivity(intent);//启动子Activity

子Activity可以onCreate()方法中,通过getInent()获得传递来的Intent对象,再通过Intent对象的getExtras()方法把Bundle数据取出。具体代码如下所示:

Intent intent=getIntent();

Bundle data=intent.getExtras();//获得Intent的extras属性

long date=data.getLong("date");//取出数据

若子Activity需要反馈用户结果给父Activity,则需要按以下步骤进行:

1) 父Activity以StartActivityForResult(Intent,int requestCode)的方法启动子Activity。

2) 子Activity在合适时机,通过setResult(int resultCode,Intent),设置结果状态,返回结果。

3) 父Activity覆写protected void onActivityResult(int requestCode, int resultCode, Intent data)方法,对子Activity返回结果进行处理。

父Activity可以启动多个子Activity,并要求这些子界面返回用户操作结果,不同子Activity以用户自定义的requestCode进行区分。子Activity使用setResult()设置结果,这会激活父界面使用onActivityResult()进行事件处理,父界面在使用requestCode区分子Activity后,就可以用同样的方法处理Intent中的extras属性携带的数据。

2.2 Fragment间消息的传递

Fragment是Android3.0新增加的特征,是可以被嵌入在Activity中,响应用户操作的UI组件。一个Activity界面中可以被嵌入一个或多个Fragment。如多标签页面,或者平板电脑中大用户界面的分块显示都需要用到Fragment。当在多个Fragment之间切换,并进行数据交换时,可以直接调用Fragment对象上setArguments(Bundle)方法设置数据,在目标Fragment中使用getArguments()来获取数据。

下面的例子假设Activity上有两个Fragment。当前显示的是Fragment1,当界面组件从Fragment1切换至Fragment2时,数据会需要从Fragment1传送到Fragment2。

/*在Fragment1的相应方法中*/

FragmentTransaction tra = getFragmentManager().beginTransaction();

Fragment fragment=new Fragment2();//初始化Fragment对象为Fragement2

Bundle args=new Bundle();

args.putLong("date", SystemClock.elapsedRealtime());

/*向Fragment2设置传递数据*/

fragment.setArguments(args);

tra.replace(R.id.fragment, fragment);//替换当前Fragment

tra.commit();

Activity中要进行Fragment的各项操作,要先获取FragmentTransaction对象,并使用它的add(),replace()或remove()方法对界面组件进行添加,替换或删除操作,并在最后使用FragmentTransaction对象的commit()方法让Fragment操作执行。从以上代码可知,Fragment2即将要显示在界面上。

Fragment要获取其他片断传递来的数据,通常在onCreateView()方法中实现代码,通过调用继承的getArguments()方法就能获得Bundle数据。

2.3 线程Thread间消息的传递

Android支持多线程编程,即一个应用程序中可以创建多个线程,同时执行多个任务。我们经常会把耗时的工作放在子线程中执行,避免UI界面延迟对用户操作的响应,当子线程执行完毕后,可能有结果需要反馈给UI线程进行界面的更新。当然除了子线程需要返回数据给UI线程,多个子线程之间可能也需要数据的交换,线程间消息传递的桥梁,是名为Handler的类。

Handler类的主要作用有两个,一个是向Handler类所在线程发送消息,另一个是帮助所在线程获取和处理消息,如图3所示。

图3 Handler工作原理

为了更好的理解Handler工作原理,需要了解与Handler一起工作的三个组件,分别是Message,Looper以及MessageQueue。

1) Message:是Handler接收和处理的消息对象。

2) MessageQueue:是消息队列,存放Message,并由Looper不断进行读取。

3) Looper:Looper类有一个loop()方法,用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息对应的Handler进行处理。每个线程都只能有一个Looper对象。

如果线程需要获取其他线程的消息,就需要在线程中创建Looper对象以及Handler对象,Looper对象,需要使用Looper.prepare()方法创建,一旦Looper对象初始化成功,系统会同时创建为线程创建MessageQueue对象。唯一例外的线程是UI主线程,Android系统在UI主线程中已经初始化了一个Looper对象,因此当UI主线程需要获取其他线程消息时,只要创建Handler对象即可。

下面的示例代码,用于非UI线程接受其他子线程的消息。需要提醒的是Looper对象的创建不能放在子线程的构造方法中,必须放在run()方法内。

public class MyThread implements Runnable {

public Handler threadHandler;//定义Handler对象为public的访问级别

@Override

public void run() {

Looper.prepare();//创建Looper对象

threadHandler=new Handler(){//创建Handler对象

@Override

public void handleMessage(Message getmsg) {

//消息的处理

}};

Looper.loop();//启动Looper对象进行消息检查

}}

若其他线程向示例中的MyThread线程发送消息,则要调用MyThread对象.threadHandler. sendMessage(Message)方法,因此子线程的Handler对象的访问级别最好设置为public,对便其他子线程方便调用。子线程中的Looper对象在MessageQueue 发现新消息后,会通知Handler对象调用 handleMessage()方法进行处理。

3 结束语

在我们实际的手机应用编程中,消息的处理非常广泛,比如用户配置界面向主界面返回配置数据,游戏程序中游戏状态需要周期性地更新UI,又如网络数据的获取反馈等。该文详细介绍并分析了Activity界面、Fragment片断以及线程Thread之间信息传递的原理和方法,对提升程序员的Android手机程序编制水平是非常有帮助的。 (下转第3008页)

(上接第2986页)

参考文献:

[1] 纪晓阳.线程在Android开发中的应用[J].软件,2013,34(8):24-26.

[2] 解志群.Android多线程与消息循环[J].电子世界,2013(19):87-88.

[3] 李刚.疯狂Android讲义[M].北京:电子工业出版社,2013.

[4] 杨丰盛.Android 技术内幕[M].北京:机械工业出版社,2011.endprint

1) Message:是Handler接收和处理的消息对象。

2) MessageQueue:是消息队列,存放Message,并由Looper不断进行读取。

3) Looper:Looper类有一个loop()方法,用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息对应的Handler进行处理。每个线程都只能有一个Looper对象。

如果线程需要获取其他线程的消息,就需要在线程中创建Looper对象以及Handler对象,Looper对象,需要使用Looper.prepare()方法创建,一旦Looper对象初始化成功,系统会同时创建为线程创建MessageQueue对象。唯一例外的线程是UI主线程,Android系统在UI主线程中已经初始化了一个Looper对象,因此当UI主线程需要获取其他线程消息时,只要创建Handler对象即可。

下面的示例代码,用于非UI线程接受其他子线程的消息。需要提醒的是Looper对象的创建不能放在子线程的构造方法中,必须放在run()方法内。

public class MyThread implements Runnable {

public Handler threadHandler;//定义Handler对象为public的访问级别

@Override

public void run() {

Looper.prepare();//创建Looper对象

threadHandler=new Handler(){//创建Handler对象

@Override

public void handleMessage(Message getmsg) {

//消息的处理

}};

Looper.loop();//启动Looper对象进行消息检查

}}

若其他线程向示例中的MyThread线程发送消息,则要调用MyThread对象.threadHandler. sendMessage(Message)方法,因此子线程的Handler对象的访问级别最好设置为public,对便其他子线程方便调用。子线程中的Looper对象在MessageQueue 发现新消息后,会通知Handler对象调用 handleMessage()方法进行处理。

3 结束语

在我们实际的手机应用编程中,消息的处理非常广泛,比如用户配置界面向主界面返回配置数据,游戏程序中游戏状态需要周期性地更新UI,又如网络数据的获取反馈等。该文详细介绍并分析了Activity界面、Fragment片断以及线程Thread之间信息传递的原理和方法,对提升程序员的Android手机程序编制水平是非常有帮助的。 (下转第3008页)

(上接第2986页)

参考文献:

[1] 纪晓阳.线程在Android开发中的应用[J].软件,2013,34(8):24-26.

[2] 解志群.Android多线程与消息循环[J].电子世界,2013(19):87-88.

[3] 李刚.疯狂Android讲义[M].北京:电子工业出版社,2013.

[4] 杨丰盛.Android 技术内幕[M].北京:机械工业出版社,2011.endprint

1) Message:是Handler接收和处理的消息对象。

2) MessageQueue:是消息队列,存放Message,并由Looper不断进行读取。

3) Looper:Looper类有一个loop()方法,用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息对应的Handler进行处理。每个线程都只能有一个Looper对象。

如果线程需要获取其他线程的消息,就需要在线程中创建Looper对象以及Handler对象,Looper对象,需要使用Looper.prepare()方法创建,一旦Looper对象初始化成功,系统会同时创建为线程创建MessageQueue对象。唯一例外的线程是UI主线程,Android系统在UI主线程中已经初始化了一个Looper对象,因此当UI主线程需要获取其他线程消息时,只要创建Handler对象即可。

下面的示例代码,用于非UI线程接受其他子线程的消息。需要提醒的是Looper对象的创建不能放在子线程的构造方法中,必须放在run()方法内。

public class MyThread implements Runnable {

public Handler threadHandler;//定义Handler对象为public的访问级别

@Override

public void run() {

Looper.prepare();//创建Looper对象

threadHandler=new Handler(){//创建Handler对象

@Override

public void handleMessage(Message getmsg) {

//消息的处理

}};

Looper.loop();//启动Looper对象进行消息检查

}}

若其他线程向示例中的MyThread线程发送消息,则要调用MyThread对象.threadHandler. sendMessage(Message)方法,因此子线程的Handler对象的访问级别最好设置为public,对便其他子线程方便调用。子线程中的Looper对象在MessageQueue 发现新消息后,会通知Handler对象调用 handleMessage()方法进行处理。

3 结束语

在我们实际的手机应用编程中,消息的处理非常广泛,比如用户配置界面向主界面返回配置数据,游戏程序中游戏状态需要周期性地更新UI,又如网络数据的获取反馈等。该文详细介绍并分析了Activity界面、Fragment片断以及线程Thread之间信息传递的原理和方法,对提升程序员的Android手机程序编制水平是非常有帮助的。 (下转第3008页)

(上接第2986页)

参考文献:

[1] 纪晓阳.线程在Android开发中的应用[J].软件,2013,34(8):24-26.

[2] 解志群.Android多线程与消息循环[J].电子世界,2013(19):87-88.

[3] 李刚.疯狂Android讲义[M].北京:电子工业出版社,2013.

[4] 杨丰盛.Android 技术内幕[M].北京:机械工业出版社,2011.endprint

猜你喜欢
主线线程调用
核电项目物项调用管理的应用研究
人物报道的多维思考、主线聚焦与故事呈现
更加突出主线 落实四个到位 推动主题教育取得实实在在成效
LabWindows/CVI下基于ActiveX技术的Excel调用
浅谈linux多线程协作
基于系统调用的恶意软件检测技术研究
下沉和整合 辽宁医改主线
基于上下文定界的Fork/Join并行性的并发程序可达性分析*
利用RFC技术实现SAP系统接口通信
Linux线程实现技术研究