Android中使用Handler&Looper更新UI范例

来源:互联网 发布:淘宝图片护盾哪里查看 编辑:程序博客网 时间:2024/05/16 23:35

5年前在学校错过一次Android,等到现在才开始补救。但愿还不晚。
本文以一个更新UI的例子来讲述Looper和Handler如何配合使用。

本文所写范例仅供研究、学习之用,不喜勿喷,敬请谅解!


UI目标:
1. 用户滑动seekBar至任意值(例如X%),然后点击UPDATE按钮,等待2s后progressBar更新到seekBar的相同值X%,底部editText_log中显示出“set progress=X”的日志。
UI设计图

多线程设计

据说,不可以做任何阻塞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线程发来的耗时任务。

两个线程的时序图如下所示:
初始化过程
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

阅读全文
0 0
原创粉丝点击