Android开发与实践课件第16章线程与消息处理.ppt

上传人:本田雅阁 文档编号:3078202 上传时间:2019-07-04 格式:PPT 页数:33 大小:1.38MB
返回 下载 相关 举报
Android开发与实践课件第16章线程与消息处理.ppt_第1页
第1页 / 共33页
Android开发与实践课件第16章线程与消息处理.ppt_第2页
第2页 / 共33页
Android开发与实践课件第16章线程与消息处理.ppt_第3页
第3页 / 共33页
Android开发与实践课件第16章线程与消息处理.ppt_第4页
第4页 / 共33页
Android开发与实践课件第16章线程与消息处理.ppt_第5页
第5页 / 共33页
点击查看更多>>
资源描述

《Android开发与实践课件第16章线程与消息处理.ppt》由会员分享,可在线阅读,更多相关《Android开发与实践课件第16章线程与消息处理.ppt(33页珍藏版)》请在三一文库上搜索。

1、,本章要求:,第16章 线程与消息处理,通过实现Runnable接口创建、开启、休眠和中断线程 建一个Handler对象发送并处理消息 开启新线程实现电子广告牌 多彩的霓虹灯 简易打地鼠游戏 开启一个新线程播放背景音乐,16.1 多线程的实现 16.2 Handler消息传递机制 16.3 综合实例多彩的霓虹灯,第16章 线程与消息处理,在程序开发时,对于一些比较耗时的操作,我们通常会为其开僻一个单独的线程来执行,这样可以尽可能减少用户的等待时间。在Android中,默认情况下,所有的操作都是在主线程中进行,这个主线程负责管理与UI相关的事件,而在我们自己创建的子线程中,又不能对UI组件进行操

2、作,因此,Android提供了消息处理传递机制来解决这一问题。本章将对Android中如何实现多线程以及如何通过线程和消息处理机制操作UI界面进行详细介绍。,第16章 线程与消息处理,16.1.1 创建线程 16.1.2 开启线程 16.1.3 线程的休眠 16.1.4 中断线程,16.1 多线程的实现,在Android中,提供了两种创建线程的方法,一种是通过Thread类的构造方法创建线程对象,并重写run()方法实现,另一种是通过实现Runnable接口实现,下面分别进行介绍。 1通过Thread类的构造方法创建线程 在Android中,可以使用Thread类提供的以下构造方法来创建线程。

3、 Thread(Runnable runnable) 该构造方法的参数runnable,可以通过创建一个Runnable类的对象并重写其run()方法来实现,例如,要创建一个名称为thread的线程,可以使用下面的代码。 Thread thread=new Thread(new Runnable() /重写run()方法 Override public void run() /要执行的操作 ); 说明: 在run()方法中,可以编写要执行的操作的代码,当线程被开启时,run()方法将会被执行。,16.1.1 创建线程,2通过实现Runnable接口创建线程 在Android中,可以通过实现Ru

4、nnable接口来创建线程。实现Runnable接口的语法格式如下: public class ClassName extends Object implements Runnable 当一个类实现Runnable接口后,还需要实现其run()方法,在run()方法中,可以编写要执行的操作的代码。 例如,要创建一个实现了Runnable接口的Activity,可以使用下面的代码。 public class MainActivity extends Activity implements Runnable Override public void onCreate(Bundle savedIns

5、tanceState) super.onCreate(savedInstanceState); setContentView(R.layout.main); Override public void run() /要执行的操作 ,创建线程对象后,还需要开启线程,线程才能执行。Thread类提供了start()方法,可以开启线程,其语法格式如下: start() 例如,存在一个名称为thread的线程,如果想开启该线程,可以使用下面的代码。 thread.start(); /开启线程,16.1.2 开启线程,线程的休眠就是让线程暂停多长时间后再次执行。同Java一样,在Android中,也可以使

6、用Thread类的sleep()方法,让线程休眠指定的时间。sleep()方法的语法格式如下: sleep(long time) 其中的参数time用于指定休眠的时间,单位为毫秒。 例如,想要线程休眠1秒钟,可以使用下面的代码。 Thread.sleep(1000);,16.1.3 线程的休眠,当需要中断指定线程时,可以使用Thread类提供的interrupt()方法来实现。使用interrupt()方法可以向指定的线程发送一个中断请求,并将该线程标记为中断状态。interrupt()方法的语法格式如下: interrupt() 例如,存在一个名称为thread的线程,如果想中断该线程,可以

7、使用下面的代码。 /省略部分代码 thread.interrupt(); /省略部分代码 public void run() while(!Thread.currentThread().isInterrupted() /省略部分代码 另外,由于当线程执行wait()、join()或者sleep()方法时,线程的中断状态将被清除,并且抛出InterruptedException,所以,如果在线程中执行了wait()、join()或者sleep()方法,那么,想要中断线程时,就需要使用,16.1.4 中断线程,一个boolean型的标记变量来记录线程的中断状态,并通过该标记变量来控制循环的执行与停

8、止。例如,通过名称为isInterrupt的boolean型变量来标记线程的中断,关键代码如下: private boolean isInterrupt=false; /定义一下标记变量 /省略部分代码 /在需要中断线程时,将isInterrupt的值设置为true public void run() while(!isInterrupt) /省略部分代码 【例16-1】 在Eclipse中创建Android项目,通过实现Runnable接口来创建线程、开启线程、让线程休眠指定时间和中断线程。(实例位置:光盘MR源码第16章16-1) (1)修改新建项目的res/layout目录下的布局文件m

9、ain.xml,将默认添加,的TextView组件删除,然后在默认添加的线性布局管理器中添加两个按钮,一个用于开启线程,另一个用于中断线程。 (2)打开默认添加的MainActivity,让该类实现Runnable接口,修改后的创建类的代码如下: public class MainActivity extends Activity implements Runnable (3)实现Runnable接口中的run()方法,在该方法中,判断当前线程是否被中断,如果没有被中断,则将循环变量+1,并在日志中输出循环变量的值,具体代码如下: Override public void run() whil

10、e (!Thread.currentThread().isInterrupted() i+; Log.i(“循环变量:“, String.valueOf(i); (4)在该MainActivity中,创建两个成员变量,具体代码如下: private Thread thread; /声明线程对象 int i; /循环变量,(5)在onCreate()方法中,首先获取布局管理器中添加的“开始”按钮,然后为该按钮添加单击事件监听器,在重写的onCreate()方法中,根据当前Activity创建一个线程,并开启该线程,具体代码如下: Button startButton = (Button) fin

11、dViewById(R.id.button1); / 获取“开始”按钮 startButton.setOnClickListener(new OnClickListener() Override public void onClick(View v) i = 0; thread = new Thread(MainActivity.this); / 创建一个线程 thread.start(); / 开启线程 ); (6)获取布局管理器中添加的“停止”按钮,并为其添加单击事件监听器,在重写的onCreate()方法中,如果thread对象不为空,则中断线程,并向日志中输出提示信息,具体代码如下:

12、Button stopButton = (Button) findViewById(R.id.button2); / 获取“停止”按钮 stopButton.setOnClickListener(new OnClickListener() Override,public void onClick(View v) if (thread != null) thread.interrupt(); / 中断线程 thread = null; Log.i(“提示:“, “中断线程“); ); (7)重写MainActivity的onDestroy()方法,在该方法中,中断线程,具体代码如下: Overr

13、ide protected void onDestroy() if (thread != null) thread.interrupt(); / 中断线程 thread = null; super.onDestroy(); ,运行本实例,在屏幕上将显示一个“开始”按钮和一个“停止”按钮,单击“开始”按钮后,将在日志面板中输出循环变量的值,单击“停止”按钮,将中断线程。日志面板的显示结果如图16-1所示。 图16-1 在日志面板中输出的内容,16.2.1 循环者Looper简介 16.2.2 消息处理类Handler简介 16.2.3 消息类Message简介,16.2 Handler消息传递机

14、制,Android中引入Handler消息传递机制,用来实现在新创建的线程中操作UI界面,本节将对Handler消息传递机制进行介绍。,16.2 Handler消息传递机制,在介绍Lopper之前,需要先来了解另一个概念,那就是MessageQueue。在Android中,一个线程对应一个Looper对象,而一个Looper对象又对应一个MessageQueue(消息队列)。MessageQueue用于存放Message(消息),在MessageQueue中,存放的消息按照FIFO(先进先出)原则执行,由于MessageQueue被封装到Looper里面了,所以这里不对MessageQueue

15、进行过多介绍。 Looper对象用来为一个线程开启一个消息循环,用来操作MessageQueue。默认情况下Android中新创建的线程是没有开启消息循环的。但是主线程除外,系统为自动为主线程创建Looper对象,开启消息循环。所以,当我们在主线程中,应用下面的代码创建Handler对象时,就不会出错,而如果在新创建的非主线程中,应用下面的代码创建Handler对象时,将产生如图16-2所示的异常信息。 Handler handler2 = new Handler();,16.2.1 循环者Looper简介,图16-2 在非主线程中创建Handler对象产生的异常信息 如果想要在非主线程中,创

16、建Handler对象,首先需要使用Looper类的prepare()方法来初始化一个Looper对象,然后创建这个Handler对象,再使用Looper类的loop()方法,启动Looper,从消息队列里获取和处理消息。 【例16-2】 在Eclipse中创建Android项目,创建一个继承了Thread类的LooperThread,并在重写的run()方法中,创建一个Handler对象发送并处理消息。(实例位置:光盘MR源码第16章16-2) (1)创建一个继承了Thread类的LooperThread,并在重写的run()方法中,创建一个Handler对象发送并处理消息,关键代码如下: p

17、ublic class LooperThread extends Thread public Handler handler1; / 声明一个Handler对象,Override public void run() super.run(); Looper.prepare(); / 初始化Looper对象 / 实例化一个Handler对象 handler1 = new Handler() public void handleMessage(Message msg) Log.i(“Looper“,String.valueOf(msg.what); ; Message m=handler1.obta

18、inMessage(); / 获取一个消息 m.what=0x11; / 设置Message的what属性的值 handler1.sendMessage(m); / 发送消息 Looper.loop(); / 启动Looper ,(2)在MainActivity的onCreate()方法中,创建一个LooperThread线程,并开启该线程,关键代码如下: LooperThread thread=new LooperThread(); /创建一个线程 thread.start(); /开启线程 运行本实例,在日志面板(LogCat)中输出如图16-3所示的内容。 图16-3 在日志面板(Log

19、Cat)中输出的内容 Looper类提供的常用方法如表16-1所示。 表16-1 Looper类提供的常用方法,注意: 写在Looper.loop()之后的代码不会被执行,这个函数内部是一个循环,当调用Handler.getLooper().quit()方法后,loop()方法才会中止,其后面的代码才能得以运行。,16.2.2 消息处理类Handler简介,消息处理类(Handler)允许发送和处理Message或Rannable对象到其所在线程的MessageQueue中。Handler有以下两个主要作用: (1)将Message或Runnable应用post()方法或sendMessage

20、()方法发送到Message Queue中,在发送时可以指定延迟时间、发送时间或者要携带的Bundle数据。当MessageQueue循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。 (2)在子线程中与主线程进行通信,也就是在工作线程中与UI线程进行通信。 说明: 在一个线程中,只能一个Looper和MessageQueue,但是,可以有多个Handler,而且这些Handler可以共享同一个Looper和MessageQueue。 Handler类提供的常用的发送和处理消息的方法如表16-2所示。 表16-2 Handler类提供的常

21、用方法,16.2.3 消息类Message简介,消息类(Message)被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Message.obtain()方法或者Handler.obtainMessage()方法获得。一个Message对象具有如表16-3所示的5个属性。 表16-3 Message类的属性 说明: 使用Message类的属性可以携带int型和数据,如果要携带其他类型的数据,可以先将要携带的数据保存到Bundle对象中,然后通过Message类的setDate()方法将其添加到Message中。,综上

22、所述,Message类的使用方法比较简单,只要在使用它时,注意以下3点即可: 尽管Message有public的默认构造方法,但是通常情况下,需要使用Message.obtain()方法或Handler.obtainMessage()方法来从消息池中获得空消息对象,以节省资源。 如果一个Message只需要携带简单的int型信息,应优先使用Message.arg1和Message.arg2属性来传递信息,这比用Bundle更省内存。 尽可能使用Message.what来标识信息,以便用不同方式处理Message。,本实例要求在Android程序中实现多彩霓虹灯的效果,运行程序,将在Androi

23、d窗口中显示一个多彩的霓虹灯,它可以不断的变换颜色,如图16-4所示。 图16-4 多彩的霓虹灯 程序开发步骤如下: (1)修改新建项目的res/layout目录下的布局文件main.xml,将默认添加的TextView组件删除,并为默认添加的线性布局管理器设置ID属性。,16.3 综合实例多彩的霓虹灯,(2)在res/values/目录下,创建一个保存颜色资源的colors.xml文件,在该文件中,定义7个颜色资源,名称依次为color1、color2、color7;颜色值分别为代表赤、橙、黄、绿、青、蓝、紫所对应的颜色值。colors.xml文件的关键代码如下: #ffff0000 #ff

24、ff6600 #ffffff00 #ff00ff00 #ff00ffff #ff0000ff #ff6600ff (3)在该MainActivity中,声明程序中所需的成员变量,具体代码如下: private Handler handler; /创建Handler对象 private static LinearLayout linearLayout; / 整体布局 public static TextView tv = new TextView14; /,TextView数组 /使用颜色资源 int bgColor=new intR.color.color1,R.color.color2,R.

25、color.color3, R.color.color4,R.color.color5,R.color.color6,R.color.color7; private int index=0; /当前颜色值 (4)在MainActivity的onCreate()方法中,首先获取线程布局管理器,然后获取屏幕的高度,接下来再通过一个for循环创建14个文本框组件,并添加到线性布局管理器中,具体代码如下: linearLayout=(LinearLayout)findViewById(R.id.ll); /获取线性布局管理器 int height=this.getResources().getDisp

26、layMetrics().heightPixels; /获取屏幕的高度 for(int i=0;itv.length;i+) tvi=new TextView(this); /创建一个文本框对象 tvi.setWidth(this.getResources().getDisplayMetrics().widthPixels); /设置文本框宽度 tvi.setHeight(height/tv.length);,/为设置文本框高度 linearLayout.addView(tvi); /将TextView组件添加到线性布局管理器中 (5)创建并开启一个新线程,在重写的run()方法中,实现一个循

27、环,在该循环中,首先获取一个Message对象,并为其设置一个消息标识,然后发送消息,最后让线程休眠1秒钟,具体代码如下: Thread t = new Thread(new Runnable() Override public void run() while (!Thread.currentThread().isInterrupted() Message m = handler.obtainMessage(); /获取一个Message m.what=0x101; /设置消息标识 handler.sendMessage(m); /发送消息 try Thread.sleep(new Rand

28、om().nextInt(1000); /休眠1秒钟, catch (InterruptedException e) e.printStackTrace(); /输出异常信息 ); t.start(); / 开启线程 (6)创建一个Handler对象,在重写的handleMessage()方法中,为每个文本框设置背景颜色,该背景颜色从颜色数组中随机获取,具体代码如下: handler = new Handler() Override public void handleMessage(Message msg) int temp=0; /临时变量 if (msg.what = 0x101) fo

29、r(int i=0;itv.length;i+) temp=new Random().nextInt(bgColor.length); /产生一个随机数,/去掉重复的并且相邻的颜色 if(index=temp) temp+; if(temp=bgColor.length) temp=0; index=temp; /为文本框设置背景 tvi.setBackgroundColor(getResources().getColor(bgColorindex); super.handleMessage(msg); ; (7)在AndroidManifest.xml文件的标记中,设置android:the

30、me属性,实现全屏显示,关键代码如下: android:theme=“android:style/Theme.Black.NoTitleBar“,(1)在现实生活中,很多事情都是同时进行的,例如,我们可以一边看书,一边喝咖啡。而计算机则可以一边播放音乐,一边打印文档。对于这种可以同时进行的任务,我们可以用线程来表示,每个线程完成一个任务,并与其他线程同时执行,这种机制被称为多线程。 (2)线程的休眠就是让线程暂停多长时间后再次执行。 (3)MessageQueue用于存放Message(消息),在MessageQueue中,存放的消息按照FIFO(先进先出)原则执行,MessageQueue被

31、封装到Looper里面了。 (4)Looper对象用来为一个线程开启一个消息循环,用来操作MessageQueue。默认情况下Android中新创建的线程是没有开启消息循环的。 (5)消息处理类(Handler)允许发送和处理Message或Rannable对象到其所在线程的MessageQueue中。 (6)消息类(Message)被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Message.obtain()方法或者Handler.obtainMessage()方法获得。,知识点提炼,16-1 在Android程序中创建线程有几种方法,分别是什么? 16-2 休眠线程需要用到Thread类的哪个方法? 16-3 如何中断一个线程? 16-4 怎样中断线程? 16-5 简单描述消息传递机制用到的几个主要类。,习题,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1