您的位置:首页 > 移动开发 > Android开发

Android线程间通信之Handler

2016-10-23 23:08 134 查看
Handler机制及基本使用也已经是老生常谈了~~~

1、概述

Android中拒绝子线程中更新UI。且主线程中过多执行耗时操作会造成界面卡顿导致ANR影响用户体验,因此Handler线程间通信的信使应运而生。Handler有两个主要用途:(1)调度消息和runnable对象作为将来的执行;及(2)将被执行在一个不同的线程自己的方法。

1.Handler基本原理

主线程(UI线程)

子线程(work线程)

Message 消息类

MessageQueue消息队列(数据结构中的队列,先进先出规则)



Handler对象发送消息对象到消息队列中,Looper循环取出消息队列中的消息对象,并将该消息对象设置为发送该消息对象的handler的handleMessage方法的参数,若消息队列中没有消息则处于阻塞状态。

2、Handler的基本使用

1.UI线程中发送消息并在UI线程中执行

Handler发送和处理消息的几个方法:

void  handleMessage(Message  msg):处理消息的方法,该方法通常被重写。
final boolean hasMessage(int  what):检查消息队列中是否包含有what属性为指定值的消息
final boolean hasMessage(int what ,Object object):检查消息队列中是否包含有what好object属性指定值的消息
sendEmptyMessage(int what):发送空消息
final Boolean send EmptyMessageDelayed(int what ,long delayMillis):指定多少毫秒发送空消息
final  boolean sendMessage(Message msg):立即发送消息
final boolean sendMessageDelayed(Message msg,long delayMillis):多少秒之后发送消息


由于代码比较简单,直接上代码了~

/**
* Created by magic on 2016年10月23日.主线程中发送消息主线程中接收
*/
@SuppressLint("HandlerLeak")
public class MainActivity extends Activity {

TextView textView;
Button button;
Handler handler = new Handler() {
// 接收消息并处理
public void handleMessage(Message msg) {
System.out.println(Thread.currentThread().getName());
// main
System.out.println("消息->" + msg.arg1 + "-" + msg.obj);
// 消息->1-obj消息
};
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
// 主线程中发送消息
Message message = handler.obtainMessage();
message.arg1 = 1;
message.obj = "obj消息";
handler.sendMessage(message);
// 输出当前线程名称
System.out.println(Thread.currentThread().getName());
// main
}
});
}

}


2.Work线程中发送消息并在UI线程中执行

/**
* Created by magic on 2016年10月23日.Work线程中发送消息 UI线程中接收消息
*/
@SuppressLint("HandlerLeak")
public class TwoActivity extends Activity {

Button button;
Handler handler = new Handler() {
// 接收消息并处理
public void handleMessage(Message msg) {
System.out.println(Thread.currentThread().getName());
// main
System.out.println("消息->" + msg.arg1 + "-" + msg.obj);
// 消息->1-obj消息
};
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

button = (Button) findViewById(R.id.btn);
button.setText("Work->UI");
button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
Thread thread = new Thread(new Runnable() {

@Override
public void run() {
// work线程中发送消息
Message message = handler.obtainMessage();
message.arg1 = 1;
message.obj = " obj消息";
System.out.println(Thread.currentThread().getName());
// Thread-400
handler.sendMessage(message);
// 输出当前线程名称
}
});
// 开启线程
thread.start();
}
});
}
}


3.UI线程中发送消息并在Work线程执行

基本步骤:

1.准备Looper对象

2.生成handler对象

3.Looper.loop()循环取出Message对象

/**
* Created by magic on 2016年10月23日.UI线程中发送消息 work线程中接收消息
*/
@SuppressLint("HandlerLeak")
public class ThreeActivity extends Activity {

Button button;
Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

textView = (TextView) findViewById(R.id.tev);
button = (Button) findViewById(R.id.btn);
button.setText("UI->Work");
button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View arg0) {
Message message = handler.obtainMessage();
message.arg1 = 1;
message.obj = " obj消息";
// 主线程中发送消息
handler.sendMessage(message);
System.out.println(Thread.currentThread().getName());
// main
}
});

new MyThread().start();
}

class MyThread extends Thread {
@Override
public void run() {
// 准备Looper对象
Looper.prepare();
handler = new Handler() {
public void handleMessage(Message msg) {
System.out.println(Thread.currentThread().getName());
// Thread-401
System.out.println("消息->" + msg.what + "-" + msg.obj);
// 消息->0- obj消息
};
};
// 循环取出消息队列中的消息对象
Looper.loop();
super.run();
}
}

}


3、Handler post方法的使用

new Handler().post(Runnable r)
new Handler().postAtFrontOfQueue(Runnable r);
new Handler().postAtTime(Runnable r, uptimeMillis);
new Handler().postAtTime(Runnable r, token, uptimeMillis);
new Handler().postDelayed(Runnable r, delayMillis);


Handler执行post方法会将参数Runnable对象,设置成Message的callback属性Message消息对象加入队列,如下:

Handler->post->Message.callback=r->join MessageQueue


该Runnable对象的run方法会在UI线程中执行,当取出Message对象时判断出该Message的callback不为null,于是调用handleCallback(msg)方法,该方法内部执行callback.run()方法。因为未开启新的线程,所以run方法内部不能执行耗时操作。

如有问题恳请指正,谢谢!

END.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐