初步窥探android线程间通讯:Handler, Looper, MessageQueue的使用方法

来源:互联网 发布:mac推荐网址下载软件 编辑:程序博客网 时间:2024/06/06 20:39

昨天看了mars老师的视频。学习了android线程间的通讯,初步熟悉了Handler, Looper, MessageQueue的用法,趁着还没忘写下来吧。

Handler、Looper、MessageQueue的作用:

Handler:它有两个作用——发送消息(sendMessage)和处理消息(handleMessage);程序使用Handler发送消息至消息队列中去,也可以处理由Looper发送过来的消息;创建Handler对象时必须重写handleMessage方法;

Looper:不断的从消息队列中取出消息对象,并调用Handler的handlerMessage方法处理消息;如果队列中没有消息对象,则其处于阻塞等待状态;

Message:Handler处理和发送的消息对象;

MessageQueue:消息队列,采用先进先出的模式(FIFO)来管理Message;

线面通过两种方式来展现线程之间的通讯,第一种是从子线程向UI程发送消息;第二种是从UI线程向主线程发送消息。

一、子线程向UI线程发送消息,代码如下:

package cui.handler_test02;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;/** * 实现线程之间的通讯 * 从子线程向UI线程发送消息"我来自另一个线程",UI线程接受到消息后打印在TextView中 * 布局文件为一个TextView和Button,很简单就不呈现了 * @author pramb * */public class MainActivity extends Activity {TextView textView;Button button;//创建一个Handler的全局变量Handler handler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.button);textView = (TextView) findViewById(R.id.textView);handler = new MyHandler();button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//按下按钮后启动子线程new Thread(new MyThread()).start();}});}class MyHandler extends Handler{//必须要重写handlerMessage方法,处理Looper传来的消息,因为怎么处理消息对象时你自己的事@Overridepublic void handleMessage(Message msg) {//收到由子线程传来的消息后先打印出当前操作的线程名字,然后打印出//传来的消息,并且更新到textView中System.out.println(Thread.currentThread().getName());System.out.println((String)msg.obj);textView.setText((String)msg.obj);}}//创建线程类class MyThread implements Runnable{@Overridepublic void run() {//获取一个消息对象,至于为什么这样获取,API上说这样获取更好,//可以自己查看一下obtainMessage()方法的介绍Message msg = handler.obtainMessage();//所发送的消息String s = "我来自另一个线程";//复制给Message的属性msg.obj = s;//向消息队列中发送消息对象handler.sendMessage(msg);//打印当前操作线程的名字System.out.println(Thread.currentThread().getName());}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();if (id == R.id.action_settings) {return true;}return super.onOptionsItemSelected(item);}}
二、由UI线程向子线程发送消息,和第一个有点不同:




package cui.handler_test03;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;/** * 实现UI线程与子线程之间的通讯,要注意与上一个实现方式不同 * 主要功能是按下按钮后先打印当前操作的线程的名字,并发送消息对象到子线程,子线程拿到 * 消息对象后,打印当前操作的线程的名字 * @author yonglin * */public class MainActivity extends Activity {Button button;Handler handler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.button);new Thread(new MyThread()).start();//点击按钮后,打印当前操作的线程,然后向子线程发送消息button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {System.out.println(Thread.currentThread().getName());Message msg = handler.obtainMessage();handler.sendMessage(msg);}});}class MyThread implements Runnable{@Overridepublic void run() {//创建Looper对象Looper.prepare();//重写handleMessage方法handler = new Handler(){@Overridepublic void handleMessage(Message msg) {//接受由UI线程发送过来的消息,并打印当前操作的线程名字System.out.println(Thread.currentThread().getName());}};//不断的从消息队列中取出消息对象,并调用handleMessage(Message msg)处理Looper.loop();}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();if (id == R.id.action_settings) {return true;}return super.onOptionsItemSelected(item);}}



上图为打印结果

两种方式的程序结构有很大的不同,仔细看一下,至于为什么不同,可以参考一下源代码,我也不大清楚;还有一点很重要:原则上不能在子线程中操作UI控件,否则会报错!其实线程间通讯我感觉就是:A线程想向B线程发送消息的话,A先把消息传入消息队列,Looper把消息从消息队列中取出,再传给B,应该就是这个意思~~~

第一次写博客,也不大会写,技术还又菜,多多包涵哈!





0 0
原创粉丝点击