




免费预览已结束,剩余8页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Android通用多个线程通信管理框架-学习笔记通用多个线程通信管理框架:1、Handler监听者框架:子线程是事件源,主线程是监听者。 Handler作为子线程的监听器出现:主线程中生成Handler的子类,并重写handleMessage(Message msg) 方法, 用来对子线程响应。子线程调用Hanlder的sendMessage(message)发送事件。view plaincopy to clipboardprint?package fy.test; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.TextView; public class MyTest extends Activity public static final int REFRESH = 0x000001; private TextView text = null; private int i = 0; private Handler mHandler = null; /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (TextView) findViewById(R.id.threadText); mHandler = new Handler() Override public void handleMessage(Message msg) if (msg.what = REFRESH) text.setText(i + ); super.handleMessage(msg); ; new MyThread().start(); public class MyThread extends Thread public void run() while (!Thread.currentThread().isInterrupted() i+; Message msg = new Message(); msg.what = REFRESH; mHandler.sendMessage(msg); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); package fy.test;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.widget.TextView;public class MyTest extends Activity public static final int REFRESH = 0x000001;private TextView text = null;private int i = 0;private Handler mHandler = null;/* Called when the activity is first created. */Overridepublic void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.main);text = (TextView) findViewById(R.id.threadText);mHandler = new Handler() Override public void handleMessage(Message msg) if (msg.what = REFRESH) text.setText(i + ); super.handleMessage(msg); ;new MyThread().start();public class MyThread extends Thread public void run() while (!Thread.currentThread().isInterrupted() i+; Message msg = new Message(); msg.what = REFRESH; mHandler.sendMessage(msg); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); 2、Handler钩子方式:在主线程中生成一个Hanlder,用Handler的Post(Runnable)方法可以将Runnable钩到主线程中运行。view plaincopy to clipboardprint?package fy.test; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; public class MyTest extends Activity private TextView text = null; private int i = 0; private Handler mHandler = null; /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (TextView) findViewById(R.id.threadText); mHandler = new Handler(); new Thread(new Runnable() Override public void run() while (true) i+; mHandler.post(new Runnable() Override public void run() text.setText(i + ); ); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); ).start(); package fy.test;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.widget.TextView;public class MyTest extends Activity private TextView text = null;private int i = 0;private Handler mHandler = null;/* Called when the activity is first created. */Overridepublic void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.main);text = (TextView) findViewById(R.id.threadText);mHandler = new Handler();new Thread(new Runnable() Override public void run() while (true) i+; mHandler.post(new Runnable() Override public void run() text.setText(i + ); ); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); ).start();注意一下代码是错误的,因为post里的线程结束后才会刷新UIview plaincopy to clipboardprint?package fy.test; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; public class MyTest extends Activity private TextView text = null; private int i = 0; private Handler mHandler = null; /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (TextView) findViewById(R.id.threadText); mHandler = new Handler(); mHandler.post(new Runnable() Override public void run() / TODO Auto-generated method stub while(true) i +; text.setText(+i); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); ); package fy.test;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.widget.TextView;public class MyTest extends Activity private TextView text = null;private int i = 0;private Handler mHandler = null;/* Called when the activity is first created. */Overridepublic void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.main);text = (TextView) findViewById(R.id.threadText);mHandler = new Handler();mHandler.post(new Runnable() Override public void run() / TODO Auto-generated method stub while(true) i +; text.setText(+i); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); );3、AsyncTask框架Activity的UI线程方案:1、runOnUiThread(Runable):view plaincopy to clipboardprint?package fy.test; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MyTest extends Activity private int x = 0; /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.main); final TextView text = (TextView) findViewById(R.id.threadText); new Thread(new Runnable() Override public void run() while(true) /需要进行的逻辑处理 x+; System.out.println(x=+x); /注:text的更新必须等到runnable里面的执行结束之后,才执行 runOnUiThread(new Runnable() public void run() text.setText(x+); ); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); ).start(); package fy.test;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;public class MyTest extends Activity private int x = 0; /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.main); final TextView text = (TextView) findViewById(R.id.threadText); new Thread(new Runnable() Override public void run() while(true) /需要进行的逻辑处理 x+; System.out.println(x=+x); /注:text的更新必须等到runnable里面的执行结束之后,才执行 runOnUiThread(new Runnable() public void run() text.setText(x+); ); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); ).start(); View的UI线程方案:1、postInvalidate()重绘,可在子线程中更新界面2、SufaceView框架-本文主要介绍Android的Handler的使用方法。Handler可以发送Messsage和Runnable对象到与其相关联的线程的消息队列。每个Handler对象与创建它的线程相关联,并且每个Handler对象只能与一个线程相关联。 Handler一般有两种用途:1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器。2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以再你的子线程中拿 到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方 法在其它线程中更新界面。 通过Runnable在子线程中更新界面的例子 在onCreate中创建Handler public class HandlerTestApp extends Activity Handler mHandler; TextView mText; /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.main); mHandler = new Handler();/创建Handler mText = (TextView) findViewById(R.id.text0);/一个TextView 构建Runnable对象,在runnable中更新界面,此处,我们修改了TextView的文字.此处需要说明的是,Runnable对象可以再主线程中创建,也可以再子线程中创建。我们此处是在子线程中创建的。 Runnable mRunnable0 = new Runnable() Override public void run() / TODO Auto-generated method stub mText.setText(This is Update from ohter thread, Mouse DOWN); ; 创建子线程,在线程的run函数中,我们向主线程的消息队列发送了一个runnable来更新界面。 private void updateUIByRunnable() new Thread() /Message msg = mHandler.obtainMessage(); public void run() /mText.setText(This is Update from ohter thread, Mouse DOWN);/这句将抛出异常 mHandler.post(mRunnable0); .start(); 用Message在子线程中来更新界面 用Message更新界面与Runnable更新界面类似,只是需要修改几个地方。 实现自己的Handler,对消息进行处理 private class MyHandler extends Handler Override public void handleMessage(Message msg) / TODO Auto-generated method stub super.handleMessage(msg); switch(msg.what) case UPDATE:/在收到消息时,对界面进行更新 mText.setText(This update by message); break; 在新的线程中发送消息 private void updateByMessage() /匿名对象 new Thread() public void run() /mText.setText(This is Update from ohter thread, Mouse DOWN); /UPDATE是一个自己定义的整数,代表了消息ID Message msg = mHandler.obtainMessage(UPDATE); mHandler.sendMessage(msg); .start(); 昨天看了看Android的线程文档,记录一些东西。Android用的是J2SE,因此在其中的线程就是Java的线程。但是Android有自己的一套框架,因此线程的使用有一些新的东西。活动与服务在Android中,程序可以分成好几个组件,其中最重要的两个就是活动(Activity)和服务(Service)。活动是用户的GUI,而服务则运行于后台。比如说,一个IM,活动就是聊天的界面,而服务则用于网络通讯。如果仅仅是这样的话,那么服务不过是一个没有界面的活动而已。但是实际上并非如此。为了节约资源,当一个活动不可见的时候,它是不会执行任何代码的,这时候就要靠服务了。例如在播放音乐的时候,就必须要用到服务,不然一切换到别的软件音乐就停了。因此服务就给程序提供了后台运行的可能。更进一步的,服务是可以远程调用的,不只这个程序可以调用它,其他程序也可以调用它(前提是有相应的接口和权限)。但是有一点要注意的是,同一个进程中的服务和活动是在同一线程中的。换句话说,后台和GUI是会相互阻塞的。这个和我的直觉有点出入,因为既然是后台服务 嘛,怎么会阻塞到前台界面呢,但是事实就是如此。因此要在服务中执行长时间的操作(如网络应用)时,还是要自己创建线程来操作。Looper和HandlerThreadAndroid在Java的线程上又加了一层,使得线程拥有了消息队列(Message Queue)的支持。提供此支持的就是Looper。一个Looper负责执行一个消息循环,当消息队列里有消息时,处理消息,否则保持休眠。通常的 GUI框架都会有消息循环与分发的概念,Android通过Looper将这个概念引入到了Java的线程中。通过它,只需要很少的代码就能为Java的 线程加入这个功能:view sourceprint?01 class LooperThread extends Thread 02 public Handler mHandler;03 04 public void run() 05 Looper.prepare();06 07 mHandler = new Handler() 08 public void handleMessage(Message msg) 09 / 在此处理新消息10 11 ;12 13 Looper.loop();14 15 其中重载Handler的handleMessage()方法来处理消息。Android提供了HandlerThread类,这个类本身就是一个支持消息循环的线程类。注意要启动一个线程还是需要手动调用start()的。HandlerHandler是用于操作线程的消息队列的类。可以用空参数创建它,这样它就自动绑定到创建它的线程的消息队列上。也可以为它提供一个Looper,这样 它就会绑定到Looper所在的线程上。Handler为不同线程之间的通信提供了方便。要和另外一个线程通信,只要得到它的Handler就行了。对于上面的示例代码,mHandler就是绑定到新创建线程的Handler(因为run()是在新的线程中运行的)。对于一个 HandlerThread,可以用getLooper()来得到它的Looper,但是要注意必须在这之前用start()启动了线程,不然是 Looper是空的(文档上没说明这点,囧了我好一阵子)。Handler的最大好处在于,它不只可以发送消息,还可以用post()来发送一个Runnable。这样一来,就可以在指定进程里面执行Runnable的run()方法中的代码了,也就是跨线程方法调用:)另外,通过将Handler绑定到自己所在的线程,然后用post()方法,可以使一段Runnable里的代码不是立刻执行,而是在线程的消息队列轮到post过去的Runnable时才执行。不过我不明白这有什么用,还请高人指点。Handler还可以指定消息/Runnable被处理的时间,这就可以把它当成定时器了(不过精确度不会太高吧)。runOnUiThread()当一个线程有结果了,要通知GUI更新呢?可以用Context的getMainLooper()来得到主线程,然后用Handler操作。但是 Activity类提供了一个简单的方法:runOnUiThread()。于是我们可以在线程中调用要更新的Activity的某个更新方法,在那个方 法里用runOnUiThread(),将要运行的代码封装在一个Runnable里喂给它就行了。以上就是目前所知道的Android里关于线程的一些方面,估计还有我不知道的东西,以后再说咯:P当第一次启动一个Android程序时,Android会自动创建一个称为“main”主线程的线程。这个主线程(也称为UI线程)很重要,因为它负责把 事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与Andriod控件交互的线程。比如,当你在屏幕上按下一个按钮后,UI线程会把这个事件 分发给刚按得那个按钮,紧接着按钮设置它自身为被按下状态并向事件队列发送一个无效(invalidate)请求。UI线程会把这个请求移出事件队列并通 知按钮在屏幕上重新绘制自身。单线程模型会在没有考虑到它的影响的情况下引起Android应用程序性能低下,因为所有的任务都在同一个线程中执行,如果执行一些耗时的操作,如访问网 络或查询数据库,会阻塞整个用户界面。当在执行一些耗时的操作的时候,不能及时地分发事件,包括用户界面重绘事件。从用户的角度来看,应用程序看上去像挂 掉了。更糟糕的是,如果阻塞应用程序的时间过长(现在大概是5秒钟)Android会向用户提示一些信息,即打开一个“应用程序没有相应 (application not responding)”的对话框。如果你想知道这有多糟糕,写一个简单的含有一个按钮的程序,并为按钮注册一个单击事件,并在事件处理器中调用这样的代码 Thread.sleep(2000)。在按下这个按钮这后恢复按钮的正常状态之前,它会保持按下状态大概2秒钟。如果这样的情况在你编写的应用程序中发 生,用户的第一反应就是你的程序运行很慢。现在你知道你应该避免在UI线程中执行耗时的操作,你很有可能会在后台线程或工作者线程中执行这些耗时的任务,这样做是否正确呢?让我们来看一个例子,在这个例子中按钮的单击事件从网络上下载一副图片并使用ImageView来展现这幅图片。代码如下:Java代码public void onClick( View v ) new Thread( new Runnable() public void run() Bitmap b = loadImageFromNetwork(); mImageView.setImageBitmap( b ); ).start(); public void onClick( View v ) new Thread( new Runnable() public void run() Bitmap b = loadImageFromNetwork(); mImageView.setImageBitmap( b ); ).start(); 这段代码好像很好地解决了你遇到的问题,因为它不会阻塞UI线程。很不幸,它违背了单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。在这段代码片段中,在一个工作者线程中使用ImageView的方法,这回引起一些很古怪的 问题。查处这个问题并修复这个bug会很困难而且也很耗时。Andriod提供了几种在其他线程中访问UI线程的方法。或许你已经对其中的一些方式很熟悉,但下面是一个更全面的列表:Activity.runOnUiThread( Runnable ) View.post( Runnable ) View.postDelayed( Runnable, long ) Hanlder 上面的任何一个类或方法都可以修复我们前面代码中出现的问题。Java代码public void onClick( View v ) new Thread( new Runnable() public void run() final Bitmap b = loadImageFromNetwork(); mImageView.post( new Runnable() mImageView.setImageBitmap( b ); ); ).start(); public void onClick( View v ) new Thread( new Runnable() public void run() final Bitmap b = loadImageFromNetwork(); mImageView.post( new Runnable() mImageView.setImageBitmap( b ); ); ).start(); 很不幸的是这些类或方法同样会使你的代码很复杂很难理解。然而当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。为了解决这个问 题,Android 1.5提供了一个工具类:AsyncTask,它
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中国卫星投资管理办法
- 《农村公路管理办法》
- 股票可转债管理办法
- 财务关于食堂管理办法
- 诗书影画院管理办法
- 装配化装修管理办法
- 上线基础资料管理办法
- 2025年收费的生产服务项目合作计划书
- 设备进出场管理办法
- 不明生物标识管理办法
- 五防系统培训
- 2025年公安辅警招聘知识考试题库及答案
- 中国热射病诊断与治疗指南(2025版)解读
- 视神经炎的护理
- 九州通业务员培训
- 儿童跑步教学课件
- 物联网技术应用专业教学标准(中等职业教育)2025修订
- 测绘保密自查管理制度
- 2026高考作文备考之题目解析及范文素材:觉醒是一种持续的心态
- 2025年《网络营销》课程标准
- DB32-T 5092-2025 低压分布式光伏接入电网数据采集要求
评论
0/150
提交评论