文档章节

Looper和Handler

k
 kim366
发布于 2016/05/13 19:15
字数 2188
阅读 7
收藏 0
         Looper用于在android线程中进行消息处理,默认情况下,一个线程并不和任何Looper绑定。当我们调用Looper.prepare()时,如果当前线程还没有和任何Looper绑定,那么将创建一个Looper让它和当前线程绑定。当我们调用Looper.loop()时,它将对当前线程所对应的Looper的消息进行处理,从消息队列里取消息,处理消息,一直循环直到对该Looper调用 quit() 函数。
注意:Looper.loop()中是个while循环,只有对它所在线程的Looper调用了quit()函数,Looper.loop()函数才能完成,其后的代码才能得以运行。一个线程对应一个Looper,一个Looper对应一个消息队列MessageQueue。
        对于Handler,其实只是把消息发送到其对应的Looper的消息队列MessageQueue中,最后的处理还是在Looper.loop()的while循环中进行的。一个Looper可以用于构造多个Handler。因为Looper.loop()函数是个while循环,会让当前线程一直在那里处理进行循环,直到对该线程的Looper调用了quit()函数,所以 如果想对该Handler发送消息或添加Runnable以进行事务处理,要么在别的线程中进行,要么在该Handler在处理消息时或在Runnable()的run()函数中进行事务处理时进行。
注意1:Handler的构造函数Handler()和Handler(Handler.Callback callback),虽然没有Looper参数,但是它实际上是通过Looper.myLooper()来获取当前线程中的Looper的。
注意2:如果你使用的Looper来自于你自己创建的线程,那么在不使用其对应的Handler时候,一定要通过 handler.getLooper().quit()来使其线程退出。
以下是Android API中的一个典型的Looper thread实现
示例1
class LooperThread extends Thread
{
public Handler mHandler ;
public void run() 
{
Looper.prepare();
mHandler = new Handler() 
{
public void handleMessage(Message msg) 
{
// process incoming messages here
}
};
Looper.loop();
}
注意:默认情况下,线程是没有Looper的,所以要调用 Looper.prepare()来给线程创建消息队列,然后再通过,Looper.loop()来不停(死循环)的处理消息消息队列的消失。
另外,Activity的MainUI线程已经新建并绑定了个Looper(在源码1的,Main函数中你可以看到)。所以在Activity中新建Handler时,不需要先调用Looper.prepare()。
关于 Activity的MainUI线程的更多内容可以查看源码文件 ActivityThread.java, 它位于 android\frameworks\base\core\java\android\app
源码1
public final class ActivityThread {
    //省略
     final ApplicationThread mAppThread = new ApplicationThread();
    final Looper mLooper = Looper.myLooper();
     final H mH = new H();
    //省略
    private final class H extends Handler  {
        //省略
    }
    //省略
     public static final void main(String[] args) {
        SamplingProfilerIntegration.start();
        Process.setArgV0("<pre-initialized>");
          Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }
         ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
          Looper.loop();
        if (Process.supportsProcesses()) {
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }

        thread.detach();
        String name = (thread.mInitialApplication != null)
            ? thread.mInitialApplication.getPackageName() : "<unknown>";
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
  }
Activity的生命周期函数(如onCreate(), onResume)本身也是通过 一个基于其MainUI线程的Looper(即ActivityThread的Main函数线程)的Handler(即ActivityThread的H mH这个Handler )来调用的.也就说这些函数都是在Looper.loop()中被执行的。当然如果我们创建了一个基于Activity本身的MainUI线程的Looper的Handler的话,该Handler的事务处理也是在Looper.loop()中进行的。我们从测试实例1也可以看到这一点。

测试实例1
package com.teleca.robin;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         Log.i(tag,"-----------------------------------------------");
StackTraceElement st[]= Thread.currentThread().getStackTrace();
for(int i=0;i<st.length;i++)
Log.i(tag,i+":"+st[i]);
Log.i(tag,"------------------------------------------------");
        handler=new Handler();
        handler.postDelayed(r, 100);
        handler2.postDelayed(r, 200);
    }
    final static String tag="robin";
    Handler handler;
     Handler handler2=new Handler();
    Runnable r=new Runnable(){
     public void run()
     {
     StackTraceElement st[]= Thread.currentThread().getStackTrace();
     for(int i=0;i<st.length;i++)
     Log.i(tag,i+":"+st[i]);
     Log.i(tag,"----------------------------------------------");
     }
     };
}
测试结果
07-20 22:10:18.799: INFO/robin(7844): -----------------------------------------------
07-20 22:10:18.819: INFO/robin(7844): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
07-20 22:10:18.819: INFO/robin(7844): 1:java.lang.Thread.getStackTrace(Thread.java:788)
07-20 22:10:18.819: INFO/robin(7844): 2:com.teleca.robin.MainActivity.onCreate(MainActivity.java:15)
07-20 22:10:18.819: INFO/robin(7844): 3:android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
07-20 22:10:18.819: INFO/robin(7844): 4:android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633)
07-20 22:10:18.819: INFO/robin(7844): 5:android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2685)
07-20 22:10:18.819: INFO/robin(7844): 6:android.app.ActivityThread.access$2300(ActivityThread.java:126)
07-20 22:10:18.819: INFO/robin(7844): 7:android.app.ActivityThread$H.handleMessage(ActivityThread.java:2038)
07-20 22:10:18.819: INFO/robin(7844): 8:android.os.Handler.dispatchMessage(Handler.java:99)
07-20 22:10:18.819: INFO/robin(7844): 9:android.os.Looper.loop(Looper.java:123)
07-20 22:10:18.819: INFO/robin(7844): 10:android.app.ActivityThread.main(ActivityThread.java:4633)
07-20 22:10:18.819: INFO/robin(7844): 11:java.lang.reflect.Method.invokeNative(Native Method)
07-20 22:10:18.819: INFO/robin(7844): 12:java.lang.reflect.Method.invoke(Method.java:521)
07-20 22:10:18.819: INFO/robin(7844): 13:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
07-20 22:10:18.819: INFO/robin(7844): 14:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
07-20 22:10:18.819: INFO/robin(7844): 15:dalvik.system.NativeStart.main(Native Method)
07-20 22:10:18.819: INFO/robin(7844): ------------------------------------------------
07-20 22:10:18.969: INFO/robin(7844): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
07-20 22:10:18.969: INFO/robin(7844): 1:java.lang.Thread.getStackTrace(Thread.java:788)
07-20 22:10:18.969: INFO/robin(7844): 2:com.teleca.robin.MainActivity$1.run(MainActivity.java:29)
07-20 22:10:18.969: INFO/robin(7844): 3:android.os.Handler.handleCallback(Handler.java:587)
07-20 22:10:18.969: INFO/robin(7844): 4:android.os.Handler.dispatchMessage(Handler.java:92)
07-20 22:10:18.969: INFO/robin(7844): 5:android.os.Looper.loop(Looper.java:123)
07-20 22:10:18.969: INFO/robin(7844): 6:android.app.ActivityThread.main(ActivityThread.java:4633)
07-20 22:10:18.969: INFO/robin(7844): 7:java.lang.reflect.Method.invokeNative(Native Method)
07-20 22:10:18.969: INFO/robin(7844): 8:java.lang.reflect.Method.invoke(Method.java:521)
07-20 22:10:18.969: INFO/robin(7844): 9:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
07-20 22:10:18.969: INFO/robin(7844): 10:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
07-20 22:10:18.969: INFO/robin(7844): 11:dalvik.system.NativeStart.main(Native Method)
07-20 22:10:18.969: INFO/robin(7844): ----------------------------------------------
07-20 22:10:19.019: INFO/robin(7844): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
07-20 22:10:19.019: INFO/robin(7844): 1:java.lang.Thread.getStackTrace(Thread.java:788)
07-20 22:10:19.019: INFO/robin(7844): 2:com.teleca.robin.MainActivity$1.run(MainActivity.java:29)
07-20 22:10:19.019: INFO/robin(7844): 3:android.os.Handler.handleCallback(Handler.java:587)
07-20 22:10:19.019: INFO/robin(7844): 4:android.os.Handler.dispatchMessage(Handler.java:92)
07-20 22:10:19.019: INFO/robin(7844): 5:android.os.Looper.loop(Looper.java:123)
07-20 22:10:19.019: INFO/robin(7844): 6:android.app.ActivityThread.main(ActivityThread.java:4633)
07-20 22:10:19.019: INFO/robin(7844): 7:java.lang.reflect.Method.invokeNative(Native Method)
07-20 22:10:19.019: INFO/robin(7844): 8:java.lang.reflect.Method.invoke(Method.java:521)
07-20 22:10:19.019: INFO/robin(7844): 9:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
07-20 22:10:19.019: INFO/robin(7844): 10:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
07-20 22:10:19.019: INFO/robin(7844): 11:dalvik.system.NativeStart.main(Native Method)
07-20 22:10:19.019: INFO/robin(7844): ----------------------------------------------

另外同过查看ActivityThread.java源码,你可以看到系统还会通过ApplicationThread mAppThread向该Handler发送消息,以便进行事务处理。

测试实例2
文件  MyService.java
package com.lenovo.robin.test;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {
String tag="robin";

      @Override
      public void onCreate() {
           Log.i(tag,"MyService is oncreate");
      }

      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
     StackTraceElement st[]= Thread.currentThread().getStackTrace();
     for(int i=0;i<st.length;i++)
     Log.i(tag,i+":"+st[i]);
           return START_STICKY;
      }
    
      @Override
      public void onDestroy() {
           Log.i(tag,"OnDestory");
      }
    
      @Override
      public IBinder onBind(Intent arg0) {
           return null;
      }
}

测试结果
08-12 22:11:30.950: I/robin(26133): MyService is oncreate
08-12 22:11:30.960: I/robin(26133): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
08-12 22:11:30.960: I/robin(26133): 1:java.lang.Thread.getStackTrace(Thread.java:745)
08-12 22:11:30.960: I/robin(26133): 2: com.lenovo.robin.test.MyService . onStartCommand (MyService.java:18)
08-12 22:11:30.960: I/robin(26133): 3:android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2456)
08-12 22:11:30.960: I/robin(26133): 4:android.app.ActivityThread.access$2800(ActivityThread.java:135)
08-12 22:11:30.960: I/robin(26133): 5:android.app.ActivityThread$H.handleMessage(ActivityThread.java:1127)
08-12 22:11:30.960: I/robin(26133): 6:android.os.Handler.dispatchMessage(Handler.java:99)
08-12 22:11:30.960: I/robin(26133): 7:android.os.Looper.loop(Looper.java:150)
08-12 22:11:30.960: I/robin(26133): 8:android.app .ActivityThread .main( ActivityThread.java:4385 )
08-12 22:11:30.960: I/robin(26133): 9:java.lang.reflect.Method.invokeNative(Native Method)
08-12 22:11:30.960: I/robin(26133): 10:java.lang.reflect.Method.invoke(Method.java:507)
08-12 22:11:30.960: I/robin(26133): 11:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
08-12 22:11:30.970: I/robin(26133): 12:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
08-12 22:11:30.970: I/robin(26133): 13:dalvik.system.NativeStart.main(Native Method)
测试实例3
文件MainActivity.java

package com . lenovo . robin . test ;
import android . os . Bundle ;
import android . app . Activity ;
import android . content . Intent ;
import android . util . Log ;
import android . view . Menu ;
import android . view . MenuItem ;
import android . view . View ;
import android . support . v4 . app . NavUtils ;
public class MainActivity extends Activity {
static boolean iscreated = false ;
final static String TAG = "robin" ;
    @Override
    public void onCreate ( Bundle savedInstanceState ) {
        super . onCreate ( savedInstanceState );
        setContentView ( R . layout . activity_main );
        iscreated = true ;
        Log . i ( TAG , "on create() in MainActivity" );
        this . startService ( new Intent ( this , MyService . class ));
    }
    @Override
    public void onDestroy () {
        Log . i ( TAG , "OnDestoryv in main" );
        super . onDestroy ();
        android . os . Process . killProcess ( android . os . Process . myPid ());
        //System.exit(1);
    }
    public void onClick(View v)
    {
    StackTraceElement st[]= Thread.currentThread().getStackTrace();
    for(int i=0;i<st.length&&i<20;i++)
    Log.w(TAG,i+":"+st[i]);
    }
}

文件layout\activity_main.xml

<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent" >
    <TextView
        android:id = "@+id/textView1"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_centerHorizontal = "true"
        android:layout_centerVertical = "true"
        android:text = "@string/hello_world"
        tools:context = ".MainActivity" />
    <Button
        android:id = "@+id/button1"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_above = "@+id/textView1"
        android:layout_alignLeft = "@+id/textView1"
        android:layout_marginBottom = "46dp"
        android:layout_marginLeft = "44dp"
        android:text = "Button"  
        android:onClick = "onClick" />
</RelativeLayout>

运行结果:
08-17 08:22:36.755: W/robin(12413): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
08-17 08:22:36.755: W/robin(12413): 1:java.lang.Thread.getStackTrace(Thread.java:745)
08-17 08:22:36.755: W/robin(12413): 2:com.lenovo.robin.test.MainActivity.onClick(MainActivity.java:32)
08-17 08:22:36.755: W/robin(12413): 3:java.lang.reflect.Method.invokeNative(Native Method)
08-17 08:22:36.755: W/robin(12413): 4:java.lang.reflect.Method.invoke(Method.java:507)
08-17 08:22:36.755: W/robin(12413): 5:android.view.View$1. onClick( View.java:2187)
08-17 08:22:36.755: W/robin(12413): 6:android.view.View. performClick (View.java:2533)
08-17 08:22:36.755: W/robin(12413): 7:android.view.View$PerformClick.run(View.java:9320)
08-17 08:22:36.755: W/robin(12413): 8:android.os.Handler.handleCallback(Handler.java:587)
08-17 08:22:36.755: W/robin(12413): 9:android.os.Handler.dispatchMessage(Handler.java:92)
08-17 08:22:36.755: W/robin(12413): 10:android.os.Looper.loop(Looper.java:150)
08-17 08:22:36.755: W/robin(12413): 11:android.app. ActivityThread . main ( ActivityThread.java:4385 )
08-17 08:22:36.755: W/robin(12413): 12:java.lang.reflect.Method.invokeNative(Native Method)
08-17 08:22:36.755: W/robin(12413): 13:java.lang.reflect.Method.invoke(Method.java:507)
08-17 08:22:36.755: W/robin(12413): 14:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
08-17 08:22:36.765: W/robin(12413): 15:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
08-17 08:22:36.765: W/robin(12413): 16:dalvik.system.NativeStart.main(Native Method)

本文转载自:http://blog.csdn.net/oyangyujun/article/details/47297259

共有 人打赏支持
k
粉丝 1
博文 129
码字总数 0
作品 0
朝阳
Android中的Looper类

Android中的Looper类,是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理。handler其实可以看做是一个工具类,用来向消息队列中插入消息的。 (1) Looper类用来为一个线...

宇宙执政
2015/12/10
88
0
Android消息机--handler的自我总结

大家都知道Handler是Android为了能在子线程更新UI所创作出来的一个类. 那么为什么Handler能在handler里面能更新UI。是因为Handler 把更新UI的操作切换到了主线程来操作. 有些博客说Handler是...

sw3458856
2016/11/11
0
0
Handler+Looper+MessageQueue深入详解

在《Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面》中,我们讲到使用Thread+Handler的方式来实现界面的更新,其实是在非UI线程发送消息到UI线程,通知UI线程进行界面更新,...

鉴客
2011/09/17
18.2K
9
笔记38 | Android线程之Looper.prepare()+Looper.loop()和HandlerThread()浅析

合抱之木,生於毫末;九層之台,起於累土;千里之行,始於足下。《老子》 地址 http://www.jianshu.com/p/dc2a4fb0fcde 目录 Looper概念 Looper实例 HandlerThread概念 HandlerThread实例 Lo...

项勇
2017/11/20
0
0
Handler消息处理机制分析

Handler经常用,然后自己总结一下下 一. What、Handler 是什么 Handler 与 Message、MessageQueue、Looper 一起构成了 Android 的消息机制,Android 系统通过大量的消息来与用户进行交互,V...

大二架构师
05/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

python标准输入输出

input() 读取键盘输入 input() 函数从标准输入读入一行文本,默认的标准输入是键盘。 input 可以接收一个Python表达式作为输入,并将运算结果返回。 print()和format()输出 format()输出...

colinux
22分钟前
0
0
Python 核心编程 (全)

浅拷贝和深拷贝 1.浅拷贝:是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容。相当于把变量里面指向的一个地址给了另一个变量就是浅拷贝,而没有创建一个新的对象,如a...

代码打碟手
34分钟前
0
0
PHP 对象比数组省内存?错!数组比对象省内存?错!

刚刚一个群里有人引出了 PHP 数组和对象占用内存谁多谁少的问题。我想起之前我好像也测试过这个问题,和群里人说的对象比数组节省内存的结论相反,我得出的是数组比对象节省内存。 但今天,我...

宇润
50分钟前
1
0
memcached命令行及其用法

21.5 memcached命令行 创建数据 yum install -y telnet 利用telnet命令连接memcached数据库 telnet 127.0.0.1 11211 #写入数据 set key2 0 30 212STORED 这个是错误的示范,因为0 30 已经...

lyy549745
50分钟前
0
0
Maven私服

Maven私服 一、简介 当多人项目开发的时候,尤其聚合项目开发,项目和项目之间需要有依赖关系,通过maven私服,可以保存互相依赖的jar包,这样的话就可把多个项目整合到一起。 如下图: Inst...

星汉
53分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部