【声明】 

迎接转发,但请保留文章原来出处→_→ 

生命壹号:http://www.cnblogs.com/smyhvae/

小说来源:http://www.cnblogs.com/smyhvae/p/4003922.html

联系格局:smyhvae@163.com 

 

【正文】

固然是国庆佳节,但也不可能终止学习的步子,作者选拔在教学商讨室为祖国阿妈默默地庆生。

至于Android的多线程知识,请参考本人从前的一篇博客:Android
八线程—-AsyncTask异步职务详解

在Android个中,提供了异步新闻处理体制的两种艺术来解决线程之间的通讯难题,一种是明天要讲的Handler的体制,还有一种正是在此之前讲过的
AsyncTask 机制。

一、handler的引入:

小编们都了解,Android
UI是线程不安全的,假使在子线程中尝试进行UI操作,程序就有大概会崩溃。相信大家在平常的办事个中都会不时碰着那些标题,消除的方案应该也是现已烂熟于心,即创办3个Message对象,然后借助Handler发送出去,之后在Handler的handleMessage()方法中拿走刚才发送的Message对象,然后在那里实行UI操作就不会再出现崩溃了。具体贯彻代码如下:

 1 package com.example.androidthreadtest;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 import android.os.Message;
 7 import android.view.View;
 8 import android.view.View.OnClickListener;
 9 import android.widget.Button;
10 import android.widget.TextView;
11 
12 public class MainActivity extends Activity implements OnClickListener {
13 
14     public static final int UPDATE_TEXT = 1;
15     private TextView text;
16     private Button changeText;
17     private Handler handler = new Handler() {
18         public void handleMessage(Message msg) {
19             switch (msg.what) {
20             case UPDATE_TEXT:
21                 text.setText("Nice to meet you");
22                 break;
23             default:
24                 break;
25             }
26         }
27     };
28 
29     @Override
30     protected void onCreate(Bundle savedInstanceState) {
31         super.onCreate(savedInstanceState);
32         setContentView(R.layout.activity_main);
33         text = (TextView) findViewById(R.id.text);
34         changeText = (Button) findViewById(R.id.change_text);
35         changeText.setOnClickListener(this);
36     }
37 
38     @Override
39     public void onClick(View v) {
40         switch (v.getId()) {
41         case R.id.change_text:
42             new Thread(new Runnable() {
43                 @Override
44                 public void run() {
45                     Message message = new Message();
46                     message.what = UPDATE_TEXT;
47                     handler.sendMessage(message);
48                 }
49             }).start();
50             break;
51         default:
52             break;
53         }
54     }
55 }

上面第陆5行代码,官方提议我们写成:(那样的话,能够由系统协调承受message的创导和销毁)

Message msg = handler.obtainMessage();

依旧写成:

Message msg = Message.obtain();

地点的代码中,大家并没有在子线程中央直机关接开始展览UI操作,而是创设了二个Message对象,并将它的what字段的值钦赐为了三个整形常量UPDATE_TEXT,用于表示更新TextView这么些动作。然后调用Handler的sendMessage()方法将那条Message发送出去。极快,Handler就会吸收那条Message,并在handleMessage()方法,在此地对现实的Message实行拍卖(需求小心的是,此时handleMessage()方法中的代码是在主线程中运转的)。若是发现Message的what字段的值等于UPDATE_TEXT,就将TextView展现的情节更新。运维程序后,点击按钮,TextView就会来得出立异的内容。

 注:要是从源码的角度驾驭,粗略的描述是那般的:

率先调用了handler的obtainMessage()方法获得Message对象。在obtainMessage()方法里做的工作是:调用了Message.obtain(this)方法,把handler作为目的传进来。在Message.obtain(this)方法里做的业务是:生成message对象,把handler作为参数赋值给message的target属性。总的来说,2个Handler对应1个Looper对象,三个Looper对应3个MessageQueue对象,使用Handler生成Message,所生成的Message对象的Target属性,正是该指标。而一个Handler能够转移三个Message,所以说,Handler和Message是一对多的涉嫌。

 

贰 、异步新闻处理体制:

Handler是Android类库提供的用于接受、传递和处理音信或Runnable对象的拍卖类,它构成Message、MessageQueue和Looper类以及当前线程完成了3个新闻循环机制,用于落到实处职分的异步加载和处理。整个异步音信处理流程的示意图如下图所示:

XML 1

依照地方的图样,我们前天来分析一下异步消息处理体制

  • Message:音信体,用于装载需求发送的指标。
  • handler:它一直接轨自Object。成效是:在子线程中发送Message恐怕Runnable对象到MessageQueue中;在UI线程中收取、处理从MessageQueue分发出来的Message大概Runnable对象。发送消息一般选拔Handler的sendMessage()方法,而发出去的音讯经过处理后最后会传递到Handler的handlerMessage()方法中。
  • MessageQueue:用于存放Message或Runnable对象的消息队列。它由相应的Looper对象创制,并由Looper对象管理。各类线程中都只会有贰个MessageQueue对象。
  • Looper:是各样线程中的MessageQueue的管家,循环不断地管理MessageQueue接收和分发Message或Runnable的工作。调用Looper的loop()方法后,就会进来到贰个最为循环中然后每当发现MessageQueue中设有一条音信,就会将它取出,并调用Handler的handlerMessage()方法。每种线程中也只会有二个Looper对象。

刺探这一个之后,大家在来看一下她俩之间的沟通

首先要理解的是,Handler和Looper对象是属于线程内部的多寡,但是也提供与表面线程的走访接口,Handler正是当着给外部线程的接口,用于线程间的通讯。Looper是由系统支持的用来创制和管理MessageQueue的附属于一个线程的大循环处理对象,而Handler是用以操作线程内部的消息队列的,所以Handler也必须依附三个线程,而且不得不是三个线程。

大家再来对异步音信处理的整套工艺流程梳理3遍:

当应用程序开启时,系统会自行为UI线程创制贰个MessageQueue(音讯队列)和Looper循环处理对象。首先要求在主线程中创设1个Handler对象,同等看待写handlerMessage()方法。然后当子线程中需求展开UI操作时,就成立二个Message对象,并经过Handler将那条音信发送出去。之后那条消息就会被添加到MessageQueue的系列中等候被拍卖,而Looper则会一向尝试从MessageQueue中取出待处理音信,并找到与音讯对象对应的Handler对象,然后调用Handler的handleMessage()方法。由于Handler是在主线程中成立的,所以那时候handleMessage()方法中的代码也会在主线程中运作,于是大家在那里就能够欣慰地展开UI操作了。

起头地来讲,一般大家在骨子里的开销进程中用的可比多一种情况的正是主线程的Handler将子线程中拍卖过的耗费时间操作的结果封装成Message(消息),并将该Message(利用主线程里的MessageQueue和Looper)传递到主线程中,最终主线程再依照传递过来的结果实行有关的UI成分的换代,从而实现职分的异步加载和拍卖,并达到线程间的通讯。

经过上一小节对Handler的四个伊始认识后,大家得以很简单总括出Handler的首要用途,上边是Android官香港网球总会结的关于Handler类的五个重要用途:

(1)执行定时任务:

内定职分时间,在有个别具体时间或有个别时刻段后执行一定的天职操作,例如使用Handler提供的postDelayed(Runnable
r,long
delayMillis)方法内定在多短时间后举办某项操作,比如当当、天猫商城、京东和微信等手机客户端的拉开界面成效,都以因此Handler定时职分来形成的。

咱俩接下去讲一下post。 

(2)线程间的通讯:

在执行较为耗费时间的操作时,Handler负责将子线程中履行的操作的结果传递到UI线程,然后UI线程再依照传递过来的结果进行相关UI成分的更新。(上边已有表明)

三、post:

对此Handler的Post格局来说,它会传递3个Runnable对象到消息队列中(那句话稍后会进行详尽说明),在这些Runnable对象中,重写run()方法。一般在那么些run()方法中写入要求在UI线程上的操作。

Post允许把三个Runnable对象入队到新闻队列中。它的方法有:post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)。详细表达如下:

  • boolean post(Runnable
    r):把二个Runnable入队到音讯队列中,UI线程从消息队列中取出这一个指标后,立刻实施。
  • boolean postAtTime(Runnable r,long
    uptimeMillis):把叁个Runnable入队到新闻队列中,UI线程从音信队列中取出这些目的后,在特定的时日实施。
  • boolean postDelayed(Runnable r,long
    delayMillis):把三个Runnable入队到新闻队列中,UI线程从消息队列中取出那个目的后,延迟delayMills秒执行
  • void removeCallbacks(Runnable r):从音讯队列中移除贰个Runnable对象。

上面通过3个德姆o,讲解怎么着通过Handler的post方式在新开发银行的线程中期维修改UI组件的品质

 1 package com.example.m03_threadtest01;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 import android.view.View;
 7 import android.widget.Button;
 8 import android.widget.TextView;
 9 
10 public class MainActivity extends Activity {
11     private Button btnMes1,btnMes2;
12     private TextView tvMessage;
13     // 声明一个Handler对象
14     private static Handler handler=new Handler();
15     
16     @Override
17     protected void onCreate(Bundle savedInstanceState) {
18         super.onCreate(savedInstanceState);
19         setContentView(R.layout.activity_main);        
20         
21         btnMes1=(Button)findViewById(R.id.button1);
22         btnMes2=(Button)findViewById(R.id.button2);
23         tvMessage=(TextView)findViewById(R.id.TextView1);
24         btnMes1.setOnClickListener(new View.OnClickListener() {
25             
26             @Override
27             public void onClick(View v) {
28                 // 新启动一个子线程
29                 new Thread(new Runnable() {                    
30                     @Override
31                     public void run() {
32                         // tvMessage.setText("...");
33                         // 以上操作会报错,无法再子线程中访问UI组件,UI组件的属性必须在UI线程中访问
34                         // 使用post方式修改UI组件tvMessage的Text属性
35                         handler.post(new Runnable() {                    
36                             @Override
37                             public void run() {
38                                 tvMessage.setText("使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。");                        
39                             }
40                         });                                
41                     }
42                 }).start();
43             }
44         });
45         
46         btnMes2.setOnClickListener(new View.OnClickListener() {
47             
48             @Override
49             public void onClick(View v) {
50                 new Thread(new Runnable() {                    
51                     @Override
52                     public void run() {
53                         // 使用postDelayed方式修改UI组件tvMessage的Text属性值
54                         // 并且延迟3S执行
55                         handler.postDelayed(new Runnable() {
56                             
57                             @Override
58                             public void run() {
59                                 tvMessage.setText("使用Handler.postDelayed在工作线程中发送一段执行到消息队列中,在主线程中延迟3S执行。");    
60                                 
61                             }
62                         }, 3000);                        
63                     }
64                 }).start();
65                 
66             }
67         });
68     }
69     
70 }

点击按钮,运维结果如下:

XML 2XML 3

有某个值得注意的是:对于Post情势而言,它里面Runnable对象的run()方法的代码(37行至39行也许58至61行),均运营在主线程上(纵然看上去是写在子线程当中的),假诺大家在那段代码里打印日志输出线程的名字,会意识输出的是Main
Thread的名字。所以对于那段代码而言,不能够实施在UI线程上的操作,一样不能使用post格局执行,比如说访问网络。 

大家今日来解释一下上面浅灰褐字体的那句话:

本条Runnable对象被停放了新闻队列其中去了,然后主线程中的Looper(因为Handler是在主线程中生成的,所以Looper也在主线程中)将这么些Runnable对象从音讯队列中取出来,取出来之后,做了些什么吗?为啥在履行Pos的Runnable对象的run()方法时,不是再一次打开二个线程呢?要询问那几个历程,只好求助Android的源代码:

开辟源码的目录sdk\sources\android-19\android\os,并找到Handler.java那些文件。找到post方法:

    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

 

上边的代码中,
能够观望,post方法其实就一行代码(326行),里面调用了sendMessageDelayed()那些方法,里面有五个参数。先看一下率先个参数getPostMessage(r):(719行)

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

 

上边的代码中,将Runnable对象赋值给Message的callback属性。注:通过翻看Message.java文件的源代码发现,callback属性是一个Runnable对象:(91行)

    /*package*/ Runnable callback;   

 

我们再来分析一下上方getPostMessage()那些措施,该措施成功了五个操作:

一是生成了1个Message对象,二是将r对象复制给Message对象的callback属性。再次回到的是三个Message对象。

再回到326行:

    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    } 

那行代码约等于:

public final boolean post(Runnable r)
{
    Message msg = getPostMessage(r);
    return sendMessage(msg);// //如果需要延时的话,这一行可以改为return sendMessageDelayed(msg,0);其中第二个参数改为具体的延时时间
}

以往应当好了然了:

首先个难题,如何把贰个Runnable对象放置音讯队列中:实际上是生成了八个Message对象,并将r赋值给Message对象的callback属性,然后再将Message对象放置到消息队列个中。

大家再看看一下Looper做了怎样。打开Looper.java的dispatchMessage的措施:(136行)

            //一个Handler对应一个Looper对象,一个Looper对应一个MessageQueue对象,
            //使用Handler生成Message,所生成的Message对象的Target属性,就是该对象    
            //Message msg = handler.obtainMessage();
            //发送一个message对象
            //handler.sendMessage(msg);
            msg.target.dispatchMessage(msg); 

那在这之中调用了dispatchMessage()方法,打开Handler.java的dispatchMessage()方法:(93至104行)

 1     /**
 2      * Handle system messages here.
 3      */
 4     public void dispatchMessage(Message msg) {
 5         if (msg.callback != null) {
 6             handleCallback(msg);
 7         } else {
 8             if (mCallback != null) {
 9                 if (mCallback.handleMessage(msg)) {
10                     return;
11                 }
12             }
13             handleMessage(msg);
14         }
15     } 

上边第⑥行代码:因为本次已经给Message的callback属性赋值了,所以就不为空,直接执行那行代码。即执行handleCallBack()那几个法子。打开handleCallBack()方法的源码:(732至734行) 

    private static void handleCallback(Message message) {
        message.callback.run();
    } 

观望这几个格局,就精神大白了:message的callback属性直接调用了run()方法,而不是敞开一个新的子线程。

今昔能够知晓了: 

第四个难点:
Looper取出了引导有r对象的Message对象现在,做的事体是:取出Message对象之后,调用了dispatchMessage()方法,然后判断Message的callback属性是不是为空,此时的callback属性是有值的,所以举行了handleCallback(Message
message),在该办法中履行了 message.callback.run()。
据书上说Java的线程知识,大家得以理解,假诺一贯调用Thread对象或许Runnable对象的run()方法,是不会开发新线程的,而是在原有的线程中执行。 

因为Looper是在主线程个中的,所以dispatchMessage()方法和handleMessage()方法也都是在主线程当中运营。所以post()里面包车型客车run方法也理所当然是在主线程个中运行的。
使用Post()方法的功利在于:制止了在主线程和子线程准将数据传来传去的难为。

 

四、Message:

Handler倘诺使用sendMessage的不二法门把新闻入队到音讯队列中,供给传递一个Message对象,而在Handler中,需求重写handleMessage()方法,用于获取工作线程传递过来的新闻,此措施运营在UI线程上。

对于Message对象,一般并不引进直接动用它的构造方法得到,而是提议通过运用Message.obtain()这一个静态的办法还是Handler.obtainMessage()获取。Message.obtain()会从音讯池中取得2个Message对象,尽管新闻池中是空的,才会利用构造方法实例化3个新Message,那样便于音讯能源的使用。并不须要担心音信池中的音信过多,它是有上限的,上限为十三个。Handler.obtainMessage()具有八个重载方法,借使查看源码,会发现实际Handler.obtainMessage()在内部也是调用的Message.obtain()。

Handler中,与Message发送音讯相关的主意有:

  • Message obtainMessage():获取叁个Message对象。
  • boolean
    sendMessage():发送1个Message对象到新闻队列中,并在UI线程取到新闻后,立刻执行。
  • boolean
    sendMessageDelayed():发送2个Message对象到音讯队列中,在UI线程取到音信后,延迟执行。
  • boolean sendEmptyMessage(int
    what):发送一个空的Message对象到行列中,并在UI线程取到信息后,立时施行。
  • boolean sendEmptyMessageDelayed(int what,long
    delayMillis):发送2个空Message对象到信息队列中,在UI线程取到新闻后,延迟执行。
  • void removeMessage():从消息队列中移除2个未响应的消息。

 

伍 、通过Handler完毕线程间通讯:

一 、在Worker Thread发送音讯,在MainThread中收取音信:

【实例】点击反扭,将人世的TextView的剧情改动为“从互联网中收获的数据”

XML 4XML 5

【实际意义】点击按钮时,程序访问服务器,服务器收到请求之后,会回去字符串结果,然后更新到程序。

完整版代码如下:

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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
      android:id="@+id/TextViewId"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="数据" />   

    <Button
        android:id="@+id/ButtonId"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送消息" 
        android:layout_below="@id/TextViewId"/>

</RelativeLayout> 

MainActivity.java代码如下:

 1 package com.example.test0207_handler;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 import android.os.Message;
 7 import android.view.Menu;
 8 import android.view.View;
 9 import android.view.View.OnClickListener;
10 import android.widget.Button;
11 import android.widget.TextView;
12 
13 public class MainActivity extends Activity {
14 
15     private TextView textView ; 
16     private Button button ;
17     private Handler handler ;
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22         
23         textView = (TextView)findViewById(R.id.TextViewId) ;
24         button = (Button)findViewById(R.id.ButtonId) ;    
25         
26         handler = new MyHandler() ;
27         
28         button.setOnClickListener(new ButtonListener()) ;
29         
30     }
31     //在MainAthread线程中接收数据,从而修改TextView的值
32     class MyHandler extends Handler {
33         @Override
34         public void handleMessage(Message msg) {
35             System.out.println("handleMessage--->"+Thread.currentThread().getName()) ;//得到当前线程的名字
36             String s = (String)msg.obj ;
37             textView.setText(s) ;
38         }
39         
40     }
41     //生成线程对象,让NetworkThread线程启动
42     class ButtonListener implements OnClickListener {
43         @Override        
44         public void onClick(View arg0) {
45             Thread t = new NetworkThread() ;
46             t.start();
47         }
48         
49     }
50     
51     //在Worker Thread线程中发送数据
52     class NetworkThread extends Thread {
53         @Override 
54         public void run(){
55             
56             System.out.println("network--->"+Thread.currentThread().getName()) ;//得到当前线程的名字
57             
58             //模拟访问网络:当线程运行时,首先休眠2秒钟
59             try {
60                 Thread.sleep(2*1000) ;
61             } catch (InterruptedException e) {
62                 e.printStackTrace();
63             }
64             //变量s的值,模拟从网络当中获取的数据
65             String s = "从网络中获取的数据" ;
66             //textView.setText(s) ; //这种做法是错误的,只有在Mainthread中才能操作UI            
67             
68             //开始发送消息
69             Message msg = handler.obtainMessage() ;    
70             msg.obj = s ;
71             handler.sendMessage(msg) ;//sendMessage()方法,在主线程或者Worker Thread线程中发送,都是可以的,都可以被取到
72         }
73     }    
74     
75     @Override
76     public boolean onCreateOptionsMenu(Menu menu) {
77         // Inflate the menu; this adds items to the action bar if it is present.
78         getMenuInflater().inflate(R.menu.main, menu);
79         return true;
80     }
81     
82 }

 那段代码的结构,和最下面的第贰章节是一致的。

上边代码中,大家在子线程中休眠2秒来模拟访问网络的操作。

65行:用字符串s表示从网络中获得的数目;70行:然后大家把那些字符串放在Message的obj属性个中发送出去,并在主线程中接收(36行)。

运营后结果如下:

XML 6

点击按钮后结果如下:

XML 7

XML 8

点击按钮后,后台输出结果如下:

XML 9

XML 10 

能够见见,子线程的名字是:Thread-1118,主线程的名字是:main。

 

贰 、在MainThread中发送音信,在Worker Thread中收到新闻:

【实例】点击按钮,在在MainThread中发送信息,在Worker
Thread中收受消息,并在后台打字与印刷输出。

【代码】完整版代码如下:

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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/ButtonId"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="在主线程中发送消息" />

</RelativeLayout> 

MainActivity.java代码如下:

 1 package com.example.m03_handle01;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 import android.os.Looper;
 7 import android.os.Message;
 8 import android.util.Log;
 9 import android.view.Menu;
10 import android.view.View;
11 import android.view.View.OnClickListener;
12 import android.widget.Button;
13 public class MainActivity extends Activity {
14     private Button button ;
15     private Handler handler ;
16     @Override
17     protected void onCreate(Bundle savedInstanceState) {
18         super.onCreate(savedInstanceState);
19         setContentView(R.layout.activity_main);
20         
21         button = (Button)findViewById(R.id.ButtonId) ;
22         
23         //当用户点击按钮时,发送Message的对象msg
24         button.setOnClickListener(new OnClickListener() {  //使用匿名内部类为button绑定监听器
25             
26             @Override
27             public void onClick(View v) {
28                 Log.i("onClick:", Thread.currentThread().getName());
29                 Message msg = handler.obtainMessage() ;
30                 handler.sendMessage(msg) ;
31             }            

32         }) ;
33         
34         WorkerThread wt = new WorkerThread() ;
35         wt.start() ;
36     }
37 
38     //在WorkerThread生成handler
39     class WorkerThread extends  Thread {
40         @Override
41         public void run() {
42             //准备Looper对象
43             Looper.prepare() ;
44             //在WorkerThread当中生成一个Handler对象
45             handler = new Handler() {
46                 @Override
47                 public void handleMessage(Message msg) {
48                     Log.i("handleMessage:", Thread.currentThread().getName());
49                     Log.i("后台输出", "收到了消息对象");
50                 }
51             };
52             //调用Looper的loop()方法之后,Looper对象将不断地从消息队列当中取出对象,然后调用handler的handleMessage()方法,处理该消息对象
53             //如果消息队列中没有对象,则该线程阻塞
54             Looper.loop() ;   //通过Looper对象将消息取出来
55         }
56         
57     }
58     
59     
60     @Override
61     public boolean onCreateOptionsMenu(Menu menu) {
62         // Inflate the menu; this adds items to the action bar if it is present.
63         getMenuInflater().inflate(R.menu.main, menu);
64         return true;
65     }
66     
67 } 

上面的第52行至54行代码:那是MainThread中发送新闻,在Worker
Thread中吸收消息的平素写法。上面包车型大巴五个步骤再另行一下:

  • 准备Looper对象
  • 在WorkerThread个中生成三个Handler对象
  • 调用Looper的loop()方法之后,Looper对象将随地地从音信队列当中取出对象,然后调用handler的handleMessage()方法,处理该音讯对象;即使音信队列中尚无对象,则该线程阻塞

专注,此时handleMessage()方法是在Worker
Thread中运作的。

运行程序后,当大家点击按钮,就会在后台输出“收到了信息对象”那句话:

XML 11

小小地总括一下:

首先实施Looper的prepare()方法,那几个措施有四个功效:一是生成Looper对象,而是把Looper对象和当前线程对象形成键值对(线程为键),存放在ThreadLocal在那之中,然后生成handler对象,调用Looper的myLooper()方法,获得与Handler所对应的Looper对象,那样的话,handler、looper
、音讯队列就形成了逐条对应的涉嫌,然后实施下边包车型大巴第12个步骤,即Looper在音信队列个中循环的取多少。

 

相关文章

网站地图xml地图