handler消息传递机制的编写代码步骤是什么(怎么使用Handler实现主线程往子线程传递消息)

:暂无数据 2026-09-22 09:00:13 :1

handler消息传递机制的编写代码步骤是什么(怎么使用Handler实现主线程往子线程传递消息)

大家好,关于handler消息传递机制的编写代码步骤是什么很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于怎么使用Handler实现主线程往子线程传递消息的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

本文目录

怎么使用Handler实现主线程往子线程传递消息

------解决方案--------------------
Looper.loop(); 之后 需要做啥?
Lopper myLopper = null;
new Thread(){
public void run(){
Looper.prepare();
myLopper = Lopper.myLooper();
Looper.loop();
}
}.start();
class Threadhandler extends Handler {
public void handleMessage(Message msg) {

}
}
Threadhandler handler = new Threadhandler(myLopper);
------解决方案--------------------
楼主牛逼,这啥需求?语句执行到Looper.loop();后,线程会阻塞在这里,后面的语句根本无法执行。
除非让loop()消息循环退出(可以调用quit()函数),否则根本无法按照你的需求来实现。
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn’t called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println("》》》》》 Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("《《《《《 Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn’t corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}

handler消息处理机制activity里写什么

在Android中,Handler是一种消息处理机制,主要用于在不同线程之间传递消息和处理消息。在Activity中,通常会使用Handler来处理异步任务中的消息,例如网络请求、后台处理等。
在Activity中使用Handler的步骤如下:
1. 在Activity中定义一个Handler对象,并重写handleMessage()方法,该方法用于处理消息。
2. 在Activity中创建一个子线程,并在子线程中使用Handler的sendMessage()方法向主线程发送消息。
3. 在主线程中,Handler会收到发送的消息,并根据不同的消息类型执行对应的操作。
以下是一个示例代码,演示了如何在Activity中使用Handler处理异步任务中的消息:
```
public class MainActivity extends AppCompatActivity {
private static final int MSG_NETWORK_REQUEST = 1;
private static final int MSG_UPDATE_UI = 2;
private Handler mHandler;

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

// 创建Handler对象,并重写handleMessage()方法
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_NETWORK_REQUEST:
// 处理网络请求结果
break;
case MSG_UPDATE_UI:
// 更新UI
break;
}
}
};

// 在子线程中使用Handler的sendMessage()方法向主线程发送消息
new Thread(new Runnable() {
@Override
public void run() {
// 执行网络请求等耗时操作
// 发送消息
mHandler.sendEmptyMessage(MSG_NETWORK_REQUEST);
}
}).start();
}
}
```
需要注意的是,Handler需要在主线程中创建,因此在Activity中创建Handler时不需要使用runOnUiThread()方法。同时,在使用Handler处理消息时,需要注意线程间的同步和数据安全等问题。

如何使用Handler实现主线程往子线程传递消息

如是窗口程序,让子线程向主线程创建的窗口发自定义消息,用SendMessage(子线程会待主线程处理完毕)或PostMessage(子线程发送消息后就继续自己的事)。 如果不是窗口程序,就必需让主线程轮询,可以用一个flag,子线程设置flag,主线程定期检...

面试:Handler 的工作原理是怎样的

Handler机制工作原理:

Handler 工作流程基本包括 Handler、Looper、Message、MessageQueue 四个部分。但我们在日常开发中,经常都只会用到 Handler 和 Message 两个类。Message 负责消息的搭载,里面有个 target 用于标记消息,obj 用于存放内容,Handler 负责消息的分发和处理。

下面具体给你讲解一下:

Handler机制是由Looper和MessageQueue来构建消息机制的。

MessageQueue:消息队列。虽然名为队列,但事实上它的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表的,其中主要有插入enqueue()和从中拿走并删除next()两个方法。

Looper:消息循环。MessageQueue来存储消息,Looper则是以无限循环的方式去查找是否有新消息,如有就去处理,若没有就standby(等待)。一个线程创建Handler时首先需要创建Looper的,不然报错:RuntimeException: No Looper; Looper.prepare() wasn’t called on this thread,而且每个线程下只需要创建一个Looper,不然会报错:RuntimeException: Only one Looper may be created per thread。

面试中回答,建议能自己总结一套自己的专属答案,并理解透,那样当遇到这个问题,就能回答的游刃有余!

android中handler如何使用

  Handler在Android中主要是负责发送和处理消息。它的主要用途大致是下面两个:
  1)按计划发送消息或执行某个Runnanble;
  2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程)
  学写一下,在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理。在实例化Handler的时候,只要有Handler的指针,任何线程也都可以sendMessage。
  Handler对于Message的处理是异步处理的。一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的(handleMessage()方法里不应该有耗时操作,可以将耗时操作放在其他线程执行,操作完后发送Message(通过sendMessges方法),然后由handleMessage()更新UI)。
  根据对视频的学习写了一个通过Button控件启动进度条(类似于下载等操作)的程序,简单介绍一下,有两个Button控件,一个是开始,点击之后会显示一个进度条以每次十分之一的进度进行(一开始是隐藏的),另一个是停止,可以中断进度。
  java代码:
  1 package zzl.handleactivity;
  2
  3 import android.app.Activity;
  4 import android.os.Bundle;
  5 import android.os.Handler;
  6 import android.os.Message;
  7 import android.view.Gravity;
  8 import android.view.View;
  9 import android.view.View.OnClickListener;
  10 import android.widget.Button;
  11 import android.widget.ProgressBar;
  12 import android.widget.Toast;
  13
  14 public class Handler_01 extends Activity {
  15
  16 //声明变量
  17 private Button startButton=null;
  18 private Button endButton=null;
  19 private ProgressBar firstBar=null;
  20 private Toast toast=null;
  21 @Override
  22 protected void onCreate(Bundle savedInstanceState) {
  23 super.onCreate(savedInstanceState);
  24 setContentView(R.layout.main);
  25
  26 //根据ID获取对象
  27 startButton =(Button)findViewById(R.id.startButton);
  28 endButton=(Button)findViewById(R.id.endButton);
  29 firstBar=(ProgressBar)findViewById(R.id.firstBar);
  30 //给对象设置动作监听器
  31 startButton.setOnClickListener(new StartButtonListener());
  32 endButton.setOnClickListener(new EndButtonListener());
  33 }
  34
  35 class StartButtonListener implements OnClickListener{
  36
  37 @Override
  38 public void onClick(View v) {
  39 // TODO Auto-generated method stub
  40 //一开始执行,加入到消息队列,不延迟,
  41 //然后马上执行run方法
  42 firstBar.setVisibility(View.VISIBLE);
  43 firstBar.setMax(100);
  44 handler.post(upRunnable);
  45 toast=Toast.makeText(Handler_01.this, "运行开始", Toast.LENGTH_SHORT);
  46 toast.setGravity(Gravity.CENTER, 0, 0);
  47 toast.show();
  48 }
  49 }
  50 class EndButtonListener implements OnClickListener{
  51
  52 @Override
  53 public void onClick(View v) {
  54 // TODO Auto-generated method stub
  55 //停止
  56 handler.removeCallbacks(upRunnable);
  57 System.out.println("It’s time to stop...");
  58 }
  59 }
  60
  61 //创建handler对象,在调用post方法
  62 //异步消息处理:将下载或者处理大数据等等单独放到另一个线程
  63 //更好的用户体验
  64 Handler handler=new Handler(){
  65
  66 @Override
  67 public void handleMessage(Message msg){
  68 firstBar.setProgress(msg.arg1);
  69 firstBar.setSecondaryProgress(msg.arg1+10);
  70 //handler.post(upRunnable);
  71 if(msg.arg1《=100) {
  72 handler.post(upRunnable); //将要执行的线程放入到队列当中
  73 }else {
  74 handler.removeCallbacks(upRunnable);
  75 }
  76 }
  77 };
  78
  79 //声明线程类:实现Runnable的接口
  80 Runnable upRunnable=new Runnable() {
  81
  82 int i=0;
  83 @Override
  84 public void run() {//程序的运行状态
  85 // TODO Auto-generated method stub
  86 //postDelayed方法:把线程对象加入到消息队列中
  87 // 隔2000ms(延迟)
  88 System.out.println("It’s time to start...");
  89 i=i+10;
  90 //获取Message消息对象
  91 Message msg=handler.obtainMessage();
  92 //将msg对象的arg1(还有arg2)对象的值设置
  93 //使用这两个变量传递消息优点:系统消耗性能较少
  94 msg.arg1=i;
  95 try{
  96 //设置当前显示睡眠1秒
  97 Thread.sleep(1000);
  98 }catch(InterruptedException e){
  99 e.printStackTrace();
  100 }
  101 //将msg对象加入到消息队列当中
  102 handler.sendMessage(msg);
  103 if(i==100){//当值满足时,将线程对象从handle中剔除
  104 handler.removeCallbacks(upRunnable);
  105 firstBar.setVisibility(View.GONE);
  106 //临时弹出
  107
  108 toast=Toast.makeText(Handler_01.this, "运行结束", Toast.LENGTH_SHORT);
  109 toast.setGravity(Gravity.CENTER, 0, 0);
  110 toast.show();
  111 }
  112 }
  113 };
  114 }
  main.xml
***隐藏网址***
***隐藏网址***
  3 android:orientation="vertical"
  4 android:layout_width="match_parent"
  5 android:layout_height="match_parent"
  6 tools:context=".Handler_01" 》
  7
  8 《ProgressBar
  9 android:id="@+id/firstBar"
  10 style="?android:attr/progressBarStyleHorizontal"
  11 android:layout_width="200dp"
  12 android:layout_height="wrap_content"
  13 android:visibility="gone"/》
  14
  15 《Button
  16 android:id="@+id/startButton"
  17 android:layout_width="wrap_content"
  18 android:layout_height="wrap_content"
  19 android:text="@string/start" /》
  20
  21 《Button
  22 android:id="@+id/endButton"
  23 android:layout_width="wrap_content"
  24 android:layout_height="wrap_content"
  25 android:text="@string/end" /》
  26
  27 《/LinearLayout》
  总结:
  1)当点击开始或者运行结束的时候,都会通过调用Toas弹出临时窗口,Toast.makeText(Handler_01.this, "运行结束", Toast.LENGTH_SHORT),这一句一开始总是执行出错,原因在于必须调用它的show方法才可以显示出来,还可以通过设置它的位置来显示;
  2)在xml中 android:text="@string/end",则需要在layout下的string文件中敲写相应的代码
  3)原本代码有一些瑕疵,就是没有下面这一段代码:
  1 if(msg.arg1《=100) {
  2 handler.post(upRunnable); //将要执行的线程放入到队列当中
  3 }else {
  4 handler.removeCallbacks(upRunnable);
  5 }
  这样就导致了upRunnable的run方法出现了死循环,这样,虽然程序UI本身没有问题,但是内部却又很大的缺陷
  这是因为
  1 if(i==100){//当值满足时,将线程对象从handle中剔除
  2 handler.removeCallbacks(upRunnable);
  3 firstBar.setVisibility(View.GONE);
  4 toast=Toast.makeText(Handler_01.this, "运行结束", Toast.LENGTH_SHORT);
  5 toast.setGravity(Gravity.CENTER, 0, 0);
  6 toast.show();
  7 }
  这一段代码看似是把upRunnable线程从线程对象队列中移除,但是再次之前又前执行了handler.sendMessage(msg);这句代码
  从而导致下面的代码又被执行到
  1 public void handleMessage(Message msg){
  2 firstBar.setProgress(msg.arg1);
  3 firstBar.setSecondaryProgress(msg.arg1+10);
  4
  5 }
  这样肯定会使upRunnable线程重新加入到线程对象队列中,updateThread的run方法重复执行,这就导致了死循环。所以必须加上之前的那段代码,通过判断来控制循环终止。并且run方法中的if(i==100)的那段代码也是可以不用的,不过我是写了一些其他代码就懒得优化了,这是后话了。
  4) 刚刚大家看到我们可以通过敲写System.out.println在logcat中显示,一开始eclipse编译器中是没有,这是如何显示出来的?
  大家可以再window的show view中找到logCat(deprecated)通过下图中绿色的“+”添加出来
  然后显示内容的时候,选择右上角“V D I W E ”的I就可以比较清晰的显示出来了,当然你也可以选择另外一个logCat来显示,方法类似。
  5)实际上,Handler在默认情况下,和调用它的Activity是处于同一个线程的。 上述Handler的使用示例中,虽然声明了线程对象,但是在实际调用当中它并没有调用线程的start()方法,而是直接调用当前线程的run()方法。
  如果要实现调用另一个新的线程,只要注释post方法,然后加上这样两段代码即可: Thread t = new Thread(r); t.start();

深入分析Android-Handler消息机制

Handler是Android消息机制的上层接口。通过它可以轻松地将一个任务切换到Handler所在的线程中去执行。通常情况下,Handler的使用场景就是 更新UI 。

在子线程中,进行耗时操作,执行完操作后,发送消息,通知主线程更新UI。

Handler消息机制主要包括: MessageQueue 、 Handler 、 Looper 这三大部分,以及 Message 。

从上面的类图可以看出:

MessageQueue、Handler和Looper三者之间的关系: 每个线程中只能存在一个Looper,Looper是保存在ThreadLocal中的。 主线程(UI线程)已经创建了一个Looper,所以在主线程中不需要再创建Looper,但是在其他线程中需要创建Looper。 每个线程中可以有多个Handler,即一个Looper可以处理来自多个Handler的消息。 Looper中维护一个MessageQueue,来维护消息队列,消息队列中的Message可以来自不同的Handler。

在子线程执行完耗时操作,当Handler发送消息时,将会调用 MessageQueue.enqueueMessage ,向消息队列中添加消息。 当通过 Looper.loop 开启循环后,会不断地从消息池中读取消息,即调用 MessageQueue.next , 然后调用目标Handler(即发送该消息的Handler)的 dispatchMessage 方法传递消息, 然后返回到Handler所在线程,目标Handler收到消息,调用 handleMessage 方法,接收消息,处理消息。

从上面可以看出,在子线程中创建Handler之前,要调用 Looper.prepare() 方法,Handler创建后,还要调用 Looper.loop() 方法。而前面我们在主线程创建Handler却不要这两个步骤,因为系统帮我们做了。

初始化Looper :

从上可以看出,不能重复创建Looper,每个线程只能创建一个。创建Looper,并保存在 ThreadLocal 。其中ThreadLocal是线程本地存储区(Thread Local Storage,简称TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。

开启Looper

创建Handler :

发送消息 :

post方法:

send方法:

如果你还想了解更多这方面的信息,记得收藏关注本站。

handler消息传递机制的编写代码步骤是什么(怎么使用Handler实现主线程往子线程传递消息)

本文编辑:admin

更多文章:


withdrawal(withdrawal是什么意思)

withdrawal(withdrawal是什么意思)

今天给各位分享withdrawal是什么意思的知识,其中也会对withdrawal是什么意思进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

2026年10月11日 07:00

根据流程图怎么编写程序(用c语言根据流程图写程序)

根据流程图怎么编写程序(用c语言根据流程图写程序)

大家好,今天小编来为大家解答以下的问题,关于根据流程图怎么编写程序,用c语言根据流程图写程序这个很多人还不知道,现在让我们一起来看看吧!

2026年10月11日 06:00

在from子句中可以出现(如何在from 子句中嵌套查询下面的语句在access中出错!)

在from子句中可以出现(如何在from 子句中嵌套查询下面的语句在access中出错!)

大家好,关于在from子句中可以出现很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于如何在from 子句中嵌套查询下面的语句在access中出错!的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望

2026年10月11日 05:20

countif函数统计个数怎么用(countif函数怎么用 详解Excel中countif函数的使用方法)

countif函数统计个数怎么用(countif函数怎么用 详解Excel中countif函数的使用方法)

其实countif函数统计个数怎么用的问题并不复杂,但是又很多的朋友都不太了解countif函数怎么用 详解Excel中countif函数的使用方法,因此呢,今天小编就来为大家分享countif函数统计个数怎么用的一些知识,希望可以帮助到大

2026年10月11日 03:30

正则匹配数字之前的字符(正则表达式如何匹配前面是数字、中间是“/”、后面也是数字,就像2/3专业的模式)

正则匹配数字之前的字符(正则表达式如何匹配前面是数字、中间是“/”、后面也是数字,就像2/3专业的模式)

本篇文章给大家谈谈正则匹配数字之前的字符,以及正则表达式如何匹配前面是数字、中间是“/”、后面也是数字,就像2/3专业的模式对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问

2026年10月11日 03:00

register语言学(register语言学)

register语言学(register语言学)

“register语言学”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看register语言学(register语言学)!

2026年10月11日 01:40

系统架构设计师可以直接考吗(学生可以报名系统架构设计师吗)

系统架构设计师可以直接考吗(学生可以报名系统架构设计师吗)

“系统架构设计师可以直接考吗”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看系统架构设计师可以直接考吗(学生可以报名系统架构设计师吗)!

2026年10月11日 01:00

orlnsertbootmediinselected(我电脑开机显示这个是什么意思or insert boot media in select)

orlnsertbootmediinselected(我电脑开机显示这个是什么意思or insert boot media in select)

大家好,如果您还对orlnsertbootmediinselected不太了解,没有关系,今天就由本站为大家分享orlnsertbootmediinselected的知识,包括我电脑开机显示这个是什么意思or insert boot med

2026年10月10日 23:00

display的用法(display是什么意思 详解display的含义和用法)

display的用法(display是什么意思 详解display的含义和用法)

大家好,如果您还对display的用法不太了解,没有关系,今天就由本站为大家分享display的用法的知识,包括display是什么意思 详解display的含义和用法的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

2026年10月10日 22:00

html全部居中代码(怎么让网页居中显示,html如何让网页居中)

html全部居中代码(怎么让网页居中显示,html如何让网页居中)

大家好,今天小编来为大家解答以下的问题,关于html全部居中代码,怎么让网页居中显示,html如何让网页居中这个很多人还不知道,现在让我们一起来看看吧!

2026年10月10日 21:10

最近更新

withdrawal(withdrawal是什么意思)
2026-10-11 07:00:01 浏览:0
热门文章

标签列表