andriod提供了 Handler 和 Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的。
在Android,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper,这个事android的新 概念。我们的主线程(UI线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handle,我们有消息循环,就要往消息循环里 面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和清除,消息的的处理,把这些都封装在Handle里面,注意Handle只是针对那 些有Looper的线程,不管是UI线程还是子线程,只要你有Looper,我就可以往你的消息队列里面添加东西,并做相应的处理。
但是这里还有一点,就是只要是关于UI相关的东西,就不能放在子线程中,因为子线程是不能操作UI的,只能进行数据、系统等其他非UI的操作。
但是这里还有一点,就是只要是关于UI相关的东西,就不能放在子线程中,因为子线程是不能操作UI的,只能进行数据、系统等其他非UI的操作。
一个Handler的创建它就会被绑定到这个线程的消息队列中,如果是在主线程创建的,那就不需要写代码来创建消息队列了,默认的消息队列会在主线程被创建。但是如果是在子线程的话,就必须在创建Handler之前先初始化线程的消息队列。如下面的代码:
Java代码
class ChildThread extends Thread {
public void run() {
/*
* 创建 handler前先初始化Looper.
*/
Looper.prepare();
/*
* 在子线程创建handler,所以会绑定到子线程的消息队列中
*
*/
mChildHandler = new Handler() {
public void handleMessage(Message msg) {
/*
* Do some expensive operations there.
*/
}
};
/*
* 启动该线程的消息队列
*/
Looper.loop();
}
}
当Handler收到消息后,就会运行handleMessage(…)的回调函数,可以在里面做一些耗时的操作。
最后完成了操作要结束子线程时,记得调用quit()来结束消息循环队列。
mChildHandler.getLooper().quit();
下面是一个线程间通信的小例子:
public class omg extends Activity
{
private static final String TAG = "MainThread";
private Handler mMainHandler = null;
private TextView info = null;
private Button msgBtn = null;
private Button btn1 = null;
private int nClick = 0;
ChildThread child1 = null;
ChildThread child2 = null;
class ChildThread extends Thread {
private Handler childHander = null;
private int nClickTimes = 0;
private static final String CHILD_TAG = "ChildThread";
public void run() {
this.setName("ChildThread");
// 初始化消息循环队列,需要在Handler创建之前
Looper.prepare();
childHander = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i(CHILD_TAG,
"Got an incoming message from the main thread - "
+ (String) msg.obj);
try {
// 在子线程中可以做一些耗时的工作
String sMsg = "";
sleep(1000);
Message toMain = new Message();
// mMainHandler.obtainMessage();
sMsg = String.valueOf(++nClickTimes);
toMain.obj = sMsg + "This is "
+ this.getLooper().getThread().getName()
+ ". 你发送了消息: \"" + (String) msg.obj + "\"?"
+ "这是弟" + sMsg + "次 ";
mMainHandler.sendMessage(toMain);
Message toChild = new Message();
toChild.obj = "over";
// mChildHandler.sendMessage(toChild);
Log.i(CHILD_TAG, "Send a message to the main thread - "
+ (String) toMain.obj);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
// 启动子线程消息循环队列
Looper.loop();
}
}
// //////////////////////////////////////////////////////////////////////////
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
info = (TextView) findViewById(R.id.info);
msgBtn = (Button) findViewById(R.id.msgBtn);
btn1 = (Button) findViewById(R.id.button1);
mMainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "Got an incoming message from the child thread - "
+ (String) msg.obj);
// 接收子线程的消息
info.setText((String) msg.obj + String.valueOf(nClick));
}
};
child1 = new ChildThread();
child1.start();
child2 = new ChildThread();
child2.start();
msgBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (child1.childHander != null) {
// 发送消息给子线程
Message childMsg = child1.childHander.obtainMessage();
Message msg = new Message();
msg.obj = mMainHandler.getLooper().getThread().getName()
+ " says Hello and msbBtn sending";
child1.childHander.sendMessage(msg);
Log.i(TAG, "Send a message to the child thread - "
+ (String) msg.obj);
}
}
});
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (child2.childHander != null) {
// 发送消息给子线程
Message childMsg = child2.childHander.obtainMessage();
Message msg = new Message();
msg.obj = mMainHandler.getLooper().getThread().getName()
+ " says Hello and btn1 sending";
child2.childHander.sendMessage(msg);
Log.i(TAG, "Send a message to the child thread - "
+ (String) msg.obj);
}
}
});
}
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Stop looping the child thread's message queue");
if (child1.childHander != null) {
child1.childHander.getLooper().quit();
}
if (child2.childHander != null) {
child2.childHander.getLooper().quit();
}
}
}
分享到:
相关推荐
Handler消息传递详解,子线程到子线程,主线程到子线程,子线程到主线程 三种消息,Looper,Handler工作机制详解 https://blog.csdn.net/shoneworn/article/details/80447651
测试Android主线程、子线程(thread、handlerThread、AsyncTask、timer)及线程间通信方式(handler、timetask、Runnable)的建立及工作过程
主线程和子线程和HandlerThread 子线程间的通信
这是我自己写的demo,练习在android中主线程给子线程发送消息
android Handler子线程计算斐波那契数列
Handler的定义:主要接受子线程发送的数据, 并用此数据配合主线程更新UI.解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个...
实现从网络上获取数据,并在TextView中进行更新,且采用viewmodel和liveData进行异步更新,主线程中将url的数据进行获取,并装入到livedata中,子线程实现下载,且将下载的数据传给主线程
Handler子线程更新ui的简单demo
http://blog.csdn.net/lindonglian/article/details/43316599
Android Handler传值的,简单的介绍了Handler的用法
android 中的五中子线程和主线程交互方式,可针对整个activity的UI或者单个View
处理不好会导致系统假死,用户体验很差,而Android则更进一步,如果任意一个Acitivity没有响应5秒钟以上就会被强制关闭,因此我们需要另外起动一个线程来处理长耗时操作,而主线程则不受其影响,在耗时操作完结发送...
3分也不高,主要是码不错,解决了android4.0以后socket无法在主线程中实现网络连接,当然暴力的方法也有,既存在即合理,暴力方法在主线程中网络连接会导致很多问题,很适合初学者来看的代码,带注释;
Android Handler类详解 Android Handler类详解 Android Handler类详解 Android Handler类详解
这个demo介绍了通过Handler在线程之间传递消息,demo中一个三个线程,主线程,发送消息的分线程,接收消息的分线程。发送消息的分线程会通知主线程更改标签文字,同时会通知接收消息的分线程更改进度条的进度。
NULL 博文链接:https://dingran.iteye.com/blog/1930178
Android Handler Looper
在主线程即UI线程外,新建一个Looper线程,并用Messenger和Handler来处理message和posted runnable。程序中,在负线程中默认加了一个3s的线程等来,来帮助理解sent message和post runnable之间的同步机制。所以在按...
android handler的一些测试,套用他人的代码做的一些测试,多个线程sendmessage,该由那个handler处理?