手记

安卓核心基础知识梳理之Android消息处理机制

Looper、Message、Handler的关系
当我们的Android应用程序的进程一创建的时候,系统就给这个进程提供了一个Looper,Looper是一个死循环,它内部维护这个一个消息队列。Looper不停地从消息队列中取消息(Message),取到消息就发送给了Handler,最后Handler根据接收到的消息去修改UI。Handler的sendMessage方法就是将消息添加到消息队列中。


  1. runOnUiThread
    Activity中提供了一个runOnUiThread方法,用于进行消息处理。此方法是通过线程合并——join来实现消息处理的。
    线程合并:主线程将子线程的任务拿到自己这里来执行并终止子线程。
    实例代码如下:
    /**
 * Runs the specified action on the UI thread. If the current thread is
         * the UI thread, then the action is executed immediately. If the
         * current thread is not the UI thread, the action is posted to the
         * event queue of the UI thread.
     * 上面的意思为:在UI线程中运行我们的任务,如果当前线程是UI线程,则立即执行,如果不是则该任务发送到UI线程的事件队列。
     */
    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            //自定义我们的业务代码
        }
    });

**postDelayed**

该方法是Handler对象提供的,Handler给消息队列发送一个消息,发送成功则返回true,否则返回false,如果返回false一般是由于looper进程不存在导致的。该方法主要用于定时任务。如果返回true也不一定代表着我们的定时任务就执行了,因为很可能在定时任务的时间未到之前我们的looper进程退出了,那么消息也就丢失了。
执行该任务的线程用的就是Handler对象所在的线程。

/**
* Causes the Runnable r to be added to the message queue, to be run
* after the specified amount of time elapses. The runnable will be run
* on the thread to which this handler is attached. Parameters: r The
* Runnable that will be executed. delayMillis The delay (in
* milliseconds) until the Runnable will be executed. Returns: Returns
* true if the Runnable was successfully placed in to the message queue.
* Returns false on failure, usually because the looper processing the
* message queue is exiting. Note that a result of true does not mean
* the Runnable will be processed -- if the looper is quit before the
* delivery time of the message occurs then the message will be dropped.
* 上面代码翻译如下:
* 该方法将一个Runnable对象r添加到消息队列,在指定的时间后会被执行。
* 这个Runnable对象会运行在当前handler所在的线程中。
* 第一个参数:Runnable 要执行的任务
* 第二个参数:delayMillis(单位:毫秒) runnable 任务被执行前的延迟时间
* 返回值:boolean ,如果该Runnable被成功添加到消息队列则返回true,否则返回false
* 不过,通常返回false是因为looper进程处理消息队列退出。
* 注意:返回true不代表着Runnable被执行,如果looper在延时任务还没被执行前退出了,那么消息就丢失掉了。
     */
    boolean flag = handler.postDelayed(new Runnable() {
        @Override
        public void run() {
        }
    }, 2000);

postAtTime
该方法也属于Handler对象,唯一不同的是该方法设置的定时任务是一个绝对时间,指的是Android系统的开机时间,如果想设置从当前时间算起2秒后执行该任务则可以将时间这样写:SystemClock.uptimeMillis()+2000,其中SystemClock.uptimeMillis()是系统运行时间。

/**
* Causes the Runnable r to be added to the message queue, to be run at
* a specific time given by uptimeMillis. The time-base is
* android.os.SystemClock.uptimeMillis. The runnable will be run on the
* thread to which this handler is attached. Parameters: r The Runnable
* that will be executed. uptimeMillis The absolute time at which the
* callback should run, using the android.os.SystemClock.uptimeMillis
* time-base. Returns: Returns true if the Runnable was successfully
* placed in to the message queue. Returns false on failure, usually
* because the looper processing the message queue is exiting. Note that
* a result of true does not mean the Runnable will be processed -- if
* the looper is quit before the delivery time of the message occurs
* then the message will be dropped.
* 意译:给消息队列发出一个消息,让指定的任务在指定的时间执行。这里的时间是绝对时间,是相对于android.os.SystemClock.uptimeMillis的时间
* 如果我们想在当前时间的2秒后执行该任务则将时间设置为:SystemClock.uptimeMillis()+2000即可。
 */
        boolean postAtTime = handler.postAtTime(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
            }
        }, SystemClock.uptimeMillis()+2000);
    }

ANR异常

  1. 简介
    Application No Response:应用程序无响应。在主线程中,是不允许执行耗时的操作的,如果主线程阻塞的时间大于6秒,就很有可能出现anr异常。
    主线程,要完成界面的更新,事件的处理,窗体显示的回调,所以如果主线程阻塞时间较长,就不能很好的处理以上比较重要的事情,那么Android有一个机制,就是如果他发现消息队列中有很多消息,主线程没办法响应的话,他就会抛出anr异常。所以,比较耗时的操作都必须要交给子线程。
  2. 解决办法
    可以通过Handler来解决这个问题,将比较耗时的操作交给子线程,然后子线程通过Handler,发送消息给主线程,让主线程去更新界面。
    什么样的操作时比较耗时的?
    1、访问网络,2、大文件的拷贝,3、阻塞式的请求,socket

结合工作和面试
  1. 面试中
     ANR异常 (常问)
    为什么为出现ANR异常,如何解决?
     Handler机制 (这个非常重要) Looper、Message、MessageQueue、Hanler如何运作的?

  2. 工作中
    这个章节非常重要,工作中用的很多。工作中如果碰到ANR异常,根据异常日志,需要会解决。需要会使用handler进行线程间通讯。
30人推荐
随时随地看视频
慕课网APP

热门评论

手记不错,四爷选中在慕课网微博推荐亲的手记,四爷期待下一篇精彩手记!~

查看全部评论