13.安卓消息处理机制

1.Android消息处理机制(★★★★必会

1.1.LooperMessageHandler的关系

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

1.2.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() {

             //自定义我们的业务代码

          }

      });

 

1.3.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);

 

1.4.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);

   }

 

 

1.5.ANR异常

1.5.1. 简介

Application No Response:应用程序无响应。在主线程中,是不允许执行耗时的操作的,如果主线程阻塞的时间大于6秒,就很有可能出现anr异常。

主线程,要完成界面的更新,事件的处理,窗体显示的回调,所以如果主线程阻塞时间较长,就不能很好的处理以上比较重要的事情,那么Android有一个机制,就是如果他发现消息队列中有很多消息,主线程没办法响应的话,他就会抛出anr异常。所以,比较耗时的操作都必须要交给子线程。

1.5.2. 解决办法

可以通过Handler来解决这个问题,将比较耗时的操作交给子线程,然后子线程通过Handler,发送消息给主线程,让主线程去更新界面。

什么样的操作时比较耗时的?

   1、访问网络,2、大文件的拷贝,3、阻塞式的请求,socket

1.6.结合工作和面试

1.     面试中

Ø  ANR异常  (常问)

为什么为出现ANR异常,如何解决?

Ø  Handler机制 (这个非常重要) 这个后期在讲项目的时候应该还会涉及到。LooperMessageMessageQueueHanler如何运作的?

2.     工作中

这个章节非常重要,工作中用的很多。工作中如果碰到ANR异常,根据异常日志,需要会解决。需要会使用handler进行线程间通讯。





posted @ 2016-08-07 21:45  杨伟乔  阅读(244)  评论(0编辑  收藏  举报