Android学习笔记48:使用Handler实时更新UI

  在Android中,主要通过MessageQueue、Looper和Handler三个类来实现Android应用程序的消息处理。其中,MessageQueue类用来描述消息队列;Looper类用来创建消息队列,以及进入消息循环;Handler类则用来发送消息和接收消息。

  本文将主要对Handler进行简要介绍,并以一个简单的实例演示如何使用Handler实时更新UI。

 

1.Handler的作用

  在Android中,当应用程序启动时,Android系统会启动一个主线程(也被称为UI线程),主要用来管理界面中的UI控件,对用户操作进行实时响应。如果我们在UI线程中进行一项非常耗时的操作,比如点击Button按钮,进行文件上传或下载,那么在这段时间内界面会出现假死现象(不响应用户操作),这显然是用户体验极差的。更为严重的是,如果在5秒内这个耗时的操作还未结束的话,Android系统会进行错误提示“强制关闭”。

  所以通常的做法是启动一个子线程,然后在子线程中来完成这些比较耗时的操作。但是,如果我们想要在子线程中更新UI,那又该如何做呢?

  因为在Android中,更新UI只可以在主线程中进行,所以想要在子线程中更新UI,就必须得子线程通知主线程,然后主线程来更新UI。

  这一过程正是通过Handler来实现的。

  子线程可以通过两种方式与Handler进行通信:Message和Runnable。使用Message可以从子线程中传递一些参数给主线程,Handler获取这些信息并进行相应的处理。使用Runnable则可以直接执行某个处理结果。其实,这两者的实质都是在Handler的队列中放入内容,Handler会处理完一个消息或者执行完某个处理之后再进行下一步操作,这样就不会出现多个线程同时要求进行UI处理而引发混乱现象。 

 

2.Handler的常用方法

  Handler的消息队列中的内容(Message或Runnable)可以设置为马上执行,延迟一定时间再执行或者指定在某个时刻执行。此外,还可以指定将其放在队列的头部,表示该内容具有最高优先级别,立刻执行。

  这些要求的设置可以通过以下一些函数来实现:

  (1)post(Runnable r);

  (2)postAtTime(Runnable r, long uptimeMillis);

  (3)postDelayed(Runnable r, long uptimeMillis);

  (4)postAtFrontOfQueue(Runnable r);

  (5)sendEmptyMessage(int what);

  (6)sendMessage(Message msg);

  (7)sendMessageAtTime(Message msg, long uptimeMillis);

  (8)sendMessageDelayed(Message msg, long uptimeMillis);

  (9)sendMessageAtFrontOfQueue(Runnable r); 

 

3.实例

  在本实例中,我们创建了一个Web工程,该Web工程很简单,仅仅是获取系统的当前时间,然后显示出来而已。

  在Tomcat上运行该Web工程,能够看到如图1所示的运行效果。

图1 Web工程运行效果

  该页面是通过一个简单的date.jsp文件来实现的。

  我们现在要做的就是,在Android工程中,通过一个TextView来显示当前页面的内容,并且在子线程中每隔1秒钟,发送一个Message给Handler,Handler收到Message通知后,完成刷新UI的操作。

  下面就来说说每一步的具体实现。

3.1在主线程中启动一个子线程

  首先,我们需要在主线程中启动一个子线程,这个比较简单,直接在MainActivity的onCreate()方法中调用如下方法即可:

  new Thread(mRunnable).start();

3.2在子线程中发送Message给Handler

  在创建子线程时,我们使用了Runnable接口对象mRunnable。这里,只需要实现Runnable接口,并重写该接口的run()方法,在run()方法中实现每1秒发送一条Message给Handler即可。具体实现方法如下:

 1     /*
 2      * Function   :   实现run()方法,每1秒发送一条Message给Handler
 3      * Author     :   博客园-依旧淡然
 4      */
 5     private Runnable mRunnable = new Runnable() {
 6         public void run() {
 7             while(true) {
 8                 try {
 9                     Thread.sleep(1000);
10                     mHandler.sendMessage(mHandler.obtainMessage());
11                 } catch (InterruptedException e) {
12                     e.printStackTrace();
13                 }
14             }
15         }
16     };

 3.3Handler接收Message通知

  最后,我们创建一个Handler对象,用来接收Message通知。在收到Message通知后,完成刷新UI的操作即可。具体实现方法如下:

 1     /*
 2      * Function   :   实现handleMessage()方法,用于接收Message,刷新UI
 3      * Author     :   博客园-依旧淡然
 4      */
 5     private Handler mHandler = new Handler() {
 6         public void handleMessage(Message msg) {
 7             super.handleMessage(msg);
 8             refreshUI();
 9         }
10     };

 3.4刷新UI

  由以上的代码可以看出,刷新UI的操作,我们是放在refreshUI()方法中来完成的。refreshUI()方法的实现也很简单,调用HttpUtils工具类中的getInputStream()方法,获得图1所示Web工程的页面内容输入流,再将该输入流转化为字符串,放入TextView控件中进行显示即可。具体实现方法如下:

 1     /*
 2      * Function   :   刷新UI
 3      * Author     :   博客园-依旧淡然
 4      */
 5     private void refreshUI() {
 6         try {
 7             InputStream inputStream = HttpUtils.getInputStream();
 8             String resultData = HttpUtils.getResultData(inputStream);
 9             mTextView.setText(resultData);
10         } catch (IOException e) {
11             e.printStackTrace();
12         }
13     }

 3.5实例效果

  最后,运行该Android工程,运行效果如图2所示,可以看到,当前时间每隔1秒会刷新一次,能够始终保持与图1所示页面的时间同步。

 

图2 运行效果

 

 

posted @ 2013-06-07 22:15  依旧淡然  阅读(17142)  评论(2编辑  收藏  举报