在自己建立的Thread中设置Handler,并接收消息
这里主要讲的是Android中线程的概念,自己的线程不能更新UI线程中的视图。如果把Handler设置在自己的线程中,那么必须建立一个Looper。至于为什么在Activity中建立Handler就不用建立一个Looper呢,因为在UI线程初始化时就已经有一个Loop了,所以直接用就行。这里还需要注意一个先后的问题。发送消息这个动作必须在线程初始化后,否则出错。至于线程初始化的时间和start()方法的执行时间无关,start()后表示进入就绪态,但没确定可以执行。
布局文件就一个Button和TextView,就不贴出来了。
MainActivity.java
package com.kale.handler; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { TextView valeTv; // 定义键值对 private String KEY = "key"; private String VALUE = "value"; // 定义一个自己的线程 class MyThread extends Thread { public Handler mHandler; @Override public void run() { System.out.println("线程开始运行"); Looper.prepare();// 在线程中必须建立一个自己的looper,不能用ui线程中的 mHandler = new Handler() {// 在新线程中创建Handler时必须创建Looper public void handleMessage(Message msg) { if (msg.what == 111) { String str = msg.getData().getString(KEY); // valeTv.setText(str);//不能更新ui Toast.makeText(MainActivity.this, str, 0).show(); } }; }; Looper.loop(); } } private MyThread thread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); valeTv = (TextView) findViewById(R.id.vale_textView); thread = new MyThread(); // 启动线程 thread.start(); //sentMsg();//发在这很危险,因为发送消息的动作可能在线程执行前,这样就出错了 } public void buttonListener(View v) { sentMsg();//因为点击事件肯定在线程开始执行后才进行,所以这里是正确的 } private void sentMsg() { // 创建消息 Message msg = new Message(); msg.what = 111; Bundle bundle = new Bundle(); bundle.putString(KEY, VALUE); // 设置数据 msg.setData(bundle); System.out.println("向线程发送消息");// 这句话必须在“线程开始运行”后打印才表示正确 // 发送消息,由于线程执行的时间不固定,这句话必须放在线程start后的一段时间才行。这里放在点击事件中,确保线程已经开始执行了。 thread.mHandler.sendMessage(msg); } }
Log表示的是正确的先后顺序,注意一下。
在处理异步操作的时候,handler + thread是个不错的选择。但是相信在使用handler的时候,大家都会遇到警告的情形,这个就是lint为开发者的提醒。handler运行于UI 线程,不断处理来自MessageQueue的消息,如果handler还有消息需要处理但是Activity页面已经结束的情况下,Activity的 引用其实并不会被回收,这就造成了内存泄漏。解决方案,一是在Activity的onDestroy方法中调用
handler.removeCallbacksAndMessages(null);取消所有的消息的处理,包括待处理的消息;二是声明handler的内部类为static。
分类:
Handler
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?