【重】使用Message、Handler更新UI

Android 2017-07-30

Thread和Runnable只是两个基本的线程类,通过他们能发挥的作用有限,但是他们是强大的Android线程类的基础类,例如Android中的HandlerThread, AsyncTask和IntentService都是以它们为基础。Thread和Runnable同时也是ThreadPoolExecutor类的基础。

有些应用在使用中会弹出一个对话框,一般这个对话框叫做应用程序无响应对话框(ANR:Application Not Responding)。虽然这个提示框有等待和关闭应用程序两种选择,但是它的弹出就已经影响了用户使用app过程中的体验,所以一般来说,Android开发的过程中都会严格控制ANR的出现。

ANR表面原因:应用在一定时间内(一般是5秒)没有响应输入操作(例如输入,按钮,手势触摸等)。

ANR根本原因:Android主线程中进行耗时操作,造成主线程阻塞;BroadcastReceiver生命周期结束前没有完成相应的耗时任务。
Android应用都是运行在主线程中的,包括activity、service的生命周期,ui的刷新(所以主线程又叫ui线程),输入响应操作等等。也就是说任何在主线程中运行的函数都不能进行耗时的动作,否则会阻塞主线程,导致输入无法响应,从而弹出ANR。
BroadcastReceiver的生命周期很短(一般为10秒),如果在它生命周期结束前耗时任务没有完成,Android认为该程序没有响应。

这些耗时的操主要包括网络,数据库,大量的计算操作(如bitmap的处理)等。

public class MainActivity extends Activity implements OnClickListener {
        
        public static final int UPDATE_TEXT = 1;
        private TextView text;
        private Button changeText;
        private Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case UPDATE_TEXT:
                        // 在这里可以进行UI操作
                        text.setText("Nice to meet you");
                        break;
                    default:
                        break;
                }
            }
        };
        ……
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.change_text:
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            Message message = new Message();
                            message.what = UPDATE_TEXT;
                            handler.sendMessage(message); // 将Message对象发送出去
                        }
                    }).start();
                    break;
                default:
                    break;
    
            }
        }
    }

这里我们先是定义了一个整型常量 UPDATE_TEXT,用于表示更新 TextView 这个动作。
然后新增一个 Handler 对象,并重写父类的 handleMessage 方法,在这里对具体的 Message
进行处理。如果发现 Message 的 what 字段的值等于 UPDATE_TEXT,就将 TextView 显示的
内容改成 Nice to meet you。
下面再来看一下 Change Text 按钮的点击事件中的代码。可以看到,这次我们并没有在
子线程里直接进行 UI 操作,而是创建了一个 Message(android.os.Message)对象,并将它
的 what 字段的值指定为 UPDATE_TEXT,然后调用 Handler 的 sendMessage()方法将这条
Message 发送出去。很快,Handler 就会收到这条 Message,并在 handleMessage()方法中对它
进行处理。注意此时 handleMessage()方法中的代码就是在主线程当中运行的了,所以我们可
以放心地在这里进行 UI 操作。接下来对 Message 携带的 what 字段的值进行判断,如果等于
UPDATE_TEXT,就将 TextView 显示的内容改成 Nice to meet you。


本文由 方方無 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论

shijiebei 365bet manbetx 188bet xinshui caipiao 95zz tongbaoyule beplay 88bifa 18luck betway bwin hg0088 aomenjinshayulecheng ca88 shenbotaiyangcheng vwin w88 weide