Android之旅--Handler与多线程
本文首先解释一下handler是用来干嘛的,然后通过例子介绍其在多线程中的应用。
什么是Handler
handler通俗一点讲就是用来在各个进程之间发送数据的处理对象。在任何进程中,只要获得了另一个进程的handler则可以通过handler.sendMessage(message)方法向那个进程发送数据。基于这个机制,我们在处理多线程的时候可以新建一个thread,这个thread拥有UI线程中的一个handler。当thread处理完一些耗时的操作后通过传递过来的handler像ui线程发送数据,由UI线程去更新界面。
handler应用多线程例子
我们这个例子是实现一个简单的词典功能。在获取网页过程中应用线程。这个程序共有两个activity,第一个用于输入查询的单词,第二个activity用于显示结果。我们直接看第二个activity的内容。(第一个activity无非是获得用户输入的单词然后传给activity2,还没有掌握的可以看我前面的文章)
首先来看OnCreate:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.queryresult); tvResult = (TextView) findViewById(R.id.tvResult); String queryString = getIntent().getStringExtra("query"); Log.d("threadId:", String.valueOf(Thread.currentThread().getId())); // 声明一个handler,它的处理程序是实现了callback的类,这里我将这个activity继承了 // callback,所以可以传入this。 handler = new Handler(this); // 新建一个线程(我们自己实现的线程),将上面的handler和查询的单词传入构造函数 GetHtmlThread thread = new GetHtmlThread(handler, getIntent() .getStringExtra("query")); // 开始线程 thread.start(); progressBar = (ProgressBar) findViewById(R.id.prb); progressBar.setVisibility(View.VISIBLE); }
一些必要的注释我已经在代码注明了。代码中的那个GetHtmlThread线程是继承于Thread的一个类,然后自己实现里面的run方法,这个和c#里面不一样。感觉还是c#里面好理解一点。那我们就看看这个GetHtmlThread类:
public class GetHtmlThread extends Thread { private Handler handler; // 传入的handler String queryKey; // 要查询的单词 public GetHtmlThread(Handler handler, String queryKey) { this.handler = handler; this.queryKey = queryKey; } @Override public void run() // 线程处理的内容 { // 获得网页中关于这个词的解释,返回的网页内容 String a = GetTranslateHtml(queryKey); // 定义一个消息,用于发给UI线程的handler处理 Message msg = new Message(); Bundle bundle = new Bundle(); // 将查询的结果放进msg中 bundle.putString("answer", a); msg.setData(bundle); // 设置这个msg的标识,这样UI中的handler才能根据这个更改对应的UI msg.what = 0; // 将消息发送给UI中的handler处理 handler.sendMessage(msg); super.run(); } }
现在线程中的消息发送出去了。我们再到UI线程中处理这个消息。代码如下:
/** * 继承了callback后,必须要实现这个方法。即上面那个handler的处理都在这里进行 */ @Override public boolean handleMessage(Message msg) { // 通过判断msg.what来判断到底是哪个"事件"要进行处理 switch (msg.what) { case 0: progressBar.setVisibility(View.GONE); // 拿出msg中的数据并显示出来 Bundle bundle = msg.getData(); tvResult.setText(bundle.getString("answer")); break; default: break; } return false; }
这样我们就可以看到当第二个activity显示一段时间后网页才显示出来,并没有出现卡死的情况!
最后再来梳理下多线程处理的步骤:
Demo下载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器