• Looper.prepare()和Looper.loop()


    什么时候需要 Looper

      Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,使用Looper.prepare()和Looper.loop()创建了消息队列就可以让消息处理在该线程中完成。

    使用Looper需要注意什么

      写在Looper.loop()之后的代码不会被立即执行,当调用后mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。

    比如下面的代码,只要调用了getLooper().quit()后代码2才会执行。

     1 class LooperThread extends Thread
     2 {
     3     4     public void run() 
     5     {
     6         Looper.prepare();
     7          //代码1....
     8         Looper.loop();
     9         //代码2....
    10     }    
    11 }        

    警惕线程未终止造成的内存泄露;譬如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程。一个典型的例子就是HandlerThread的run方法是一个死循环,它不会自己结束,线程的生命周期超过了Activity生命周期,我们必须手动在Activity的销毁方法中中调运thread.getLooper().quit();才不会泄露。

    Looper与Activity

    Activity的MainUI线程默认是有消息队列的。所以在Activity中新建Handler时,不需要先调用Looper.prepare()

    主线程中的Looper.loop()一直无限循环为什么不会造成ANR

    ActivityThread.java 是主线程入口的类,这里你可以看到写Java程序中司空见惯的main方法,而main方法正是整个Java程序的入口。

    ActivityThread源码

    1 public static final void main(String[] args) {
    2         ...
    3         //创建Looper和MessageQueue
    4         Looper.prepareMainLooper();
    5         ...
    6         //轮询器开始轮询
    7         Looper.loop();
    8         ...
    9     }

    Looper.loop()方法

    1  while (true) {
    2        //取出消息队列的消息,可能会阻塞
    3        Message msg = queue.next(); // might block
    4        ...
    5        //解析消息,分发消息
    6        msg.target.dispatchMessage(msg);
    7        ...
    8     }

    ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了。那为什么这个死循环不会造成ANR异常呢?

    因为Android 的是由事件驱动的,looper.loop() 不断地接收事件、处理事件,每一个点击触摸或者说Activity的生命周期都是运行在 Looper.loop() 的控制之下,如果它停止了,应用也就停止了。只能是某一个消息或者说对消息的处理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。也就说我们的代码其实就是在这个循环里面去执行的,当然不会阻塞了。


    handleMessage方法部分源码

     1 public void handleMessage(Message msg) {
     2         if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
     3         switch (msg.what) {
     4             case LAUNCH_ACTIVITY: {
     5                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
     6                 final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
     7                 r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
     8                 handleLaunchActivity(r, null);
     9                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    10             }
    11             break;
    12             case RELAUNCH_ACTIVITY: {
    13                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
    14                 ActivityClientRecord r = (ActivityClientRecord) msg.obj;
    15                 handleRelaunchActivity(r);
    16                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    17             }
    18             break;
    19             case PAUSE_ACTIVITY:
    20                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    21                 handlePauseActivity((IBinder) msg.obj, false, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 2) != 0);
    22                 maybeSnapshot();
    23                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    24                 break;
    25             case PAUSE_ACTIVITY_FINISHING:
    26                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    27                 handlePauseActivity((IBinder) msg.obj, true, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 1) != 0);
    28                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    29                 break;
    30             ...........
    31         }
    32     }

    可以看见Activity的生命周期都是依靠主线程的Looper.loop,当收到不同Message时则采用相应措施。

    如果某个消息处理时间过长,比如你在onCreate(),onResume()里面处理耗时操作,那么下一次的消息比如用户的点击事件不能处理了,整个循环就会产生卡顿,时间一长就成了ANR。


    总结

      Looper: 每个线程只有一个Looper,负责管理MessageQueue,会不断地从MessageQueue中取出消息,并将消息分给对应的Handler处理。

      MessageQueue:由Looper负责管理,采用先进先出的方式管理Message(消息队列)。

      Handler:把消息发送给Looper管理的MessageQueue并负责处理Looper分给它的消息。

      消息只能在某个具体的Looper上消耗,因此每个Handler都会绑定一个Looper。但是多个Handler可以绑定同一个Looper(这也是在主线程中能够创建新的Handler的原因)。

    引用:http://www.jianshu.com/p/cfe50b8b0a41
     
  • 相关阅读:
    如何查看ubuntu版本
    基于Python与命令行人脸识别项目(系列一)
    问题 B: Curriculum Vitae
    问题 M: 克隆玩具
    1906: 鹊桥相会
    3265: 聪明的矿工
    2363: 完美旗手队列
    2545: 内部收益率
    2544: 台球碰撞
    3272: 公民身份号码
  • 原文地址:https://www.cnblogs.com/l2rf/p/6055218.html
Copyright © 2020-2023  润新知