Android中使用Handler&Looper更新UI范例
16lz
2021-01-25
5年前在学校错过一次Android,等到现在才开始补救。但愿还不晚。
本文以一个更新UI的例子来讲述Looper和Handler如何配合使用。
本文所写范例仅供研究、学习之用,不喜勿喷,敬请谅解!
UI目标:
1. 用户滑动seekBar至任意值(例如X%),然后点击UPDATE按钮,等待2s后progressBar更新到seekBar的相同值X%,底部editText_log中显示出“set progress=X”的日志。
多线程设计
据说,不可以做任何阻塞UI的工作!
本文设计一共两个线程:UI线程 + Looper线程。
两个线程的职责分别是:
UI线程:UI启动、处理UI消息、更新UI。
Looper线程:处理耗时2s的复杂任务,处理完毕后返回消息给UI线程。
本文设计了两个Handler,分别是:MainHandler + LooperHandler。
两个Handler的职责分别是:
MainHandler:
1. 由Looper线程调用,发送更新UI的消息到UI线程;
2. 由UI线程处理Message时被调用处理UI更新的Message,更新UI。
LooperHandler:
1. 由UI线程调用,发送处理任务的消息给Looper线程;
2. 在Looper线程中调用,处理从UI线程发来的耗时任务。
两个线程的时序图如下所示:
部分实现代码如下:
package com.frank.simplehandler_0611;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.SeekBar;public class MainActivity extends AppCompatActivity { private static final String TAG = "SimpleHandler_0611"; public static class MyLooperHandler extends Handler { private MainHandler mMainHandler = null; private static final int MSG_SET_PROGRESS = 0; public MyLooperHandler(Looper looper, MainHandler mainHandler) { super(looper); mMainHandler = mainHandler; } /**** * handleMessage called in LooperThread. * * @param msg message object. */ @Override public void handleMessage(Message msg) { if (msg.what == MSG_SET_PROGRESS) { Log.d(TAG, "MyLooperHandler.handleMessage msg.what=" + msg.what + " arg1=" + msg.arg1); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } mMainHandler.updateProgress(msg.arg1); } } /*** * setProgress called in Main Thread. * * @param arg0 new seek bar value. */ public void setProgress(int arg0) { Log.d(TAG, "MyLooperHandler.setProgress arg0=" + arg0); Message msg = Message.obtain(); msg.what = MSG_SET_PROGRESS; msg.arg1 = arg0; sendMessage(msg); } } public class MainHandler extends Handler { public static final int MSG_SET_PROGRESS_MAIN = 1; public MainHandler(Looper looper) { super(looper); } /*** * handleMessage called in UI thread * * @param msg */ @Override public void handleMessage(Message msg) { if (msg.what == MSG_SET_PROGRESS_MAIN) { int prg = msg.arg1; String content = (String) msg.obj; Log.d(TAG, "MainHandler.handleMessage msg.what=" + msg.what + " progress=" + prg + " content=" + content); if (progressBar_01 != null) { progressBar_01.setProgress(prg); } if (editText_log != null) { editText_log.append(content); } } } /*** * updateProgress called in MyLooperThread * This message is send to Main Thread for UI update * * @param arg */ public void updateProgress(int arg) { Log.d(TAG, "MainHandler.updateProgress arg=" + arg); Message msg = Message.obtain(); msg.what = MSG_SET_PROGRESS_MAIN; msg.arg1 = arg; msg.obj = String.format("set progress=%d", arg); sendMessage(msg); } } MyLooperHandler myLooperHandler = null; MainHandler mainHandler = null; EditText editText_log = null; SeekBar seekBar_01 = null; ProgressBar progressBar_01 = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "MainActivity.onCreate UI thread running..."); // UI components initialize editText_log = (EditText) findViewById(R.id.editText_log); seekBar_01 = (SeekBar) findViewById(R.id.seekBar_01); progressBar_01 = (ProgressBar) findViewById(R.id.progressBar_01); findViewById(R.id.button_action).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (seekBar_01 != null) { int prg = seekBar_01.getProgress(); if (myLooperHandler != null) { Log.d(TAG, "MainActivity.onCreate.button_action.onClick prg=" + prg); myLooperHandler.setProgress(prg); } } } }); MyLooperThread myLooperThread = new MyLooperThread("Worker"); myLooperThread.start(); mainHandler = new MainHandler(getMainLooper()); myLooperHandler = new MyLooperHandler(myLooperThread.getLooper(), mainHandler); }}
代码工程详见:
https://github.com/wangqunfeng/AndroidDemos/tree/master/apps/SimpleHandler_0611
更多相关文章
- Android(安卓)使用RxJava+Retrofit 2.0合并网络请求
- Handler消息机制的原理及应用场景
- Android重拾 — handle
- Android(安卓)binder from Top to Bottom
- java/android 设计模式学习笔记(1)---单例模式
- 关于Android(安卓)开发优化的建议
- Android中利用Handler实现消息的分发机制(三)
- Handle机制详解
- [转] android 中 任务、进程和线程的区别