Android 消息机制与Handler和线程的关系

来源:互联网 发布:在淘宝买二手书被坑了 编辑:程序博客网 时间:2024/05/23 19:13

Android消息机制

    ·Android不可避免要操作一些耗时操作

       ·主线程堵塞影响用户交互,需要运行完后通知主线程更新

    ·下面我们来了解下Android的消息机制

                                          

               在主线程创建完成后系统会默认的创建一个looper对象,他就是个循环操作,循环的读取系统为主线程创建  好的 Message Queue中的消息(Messa Queue 中存放着许多的MSg),当looper读取到一个消息时候会为这个消息进行操作处理,当对应的处理执行完成后消息(msg)会被移除出消息队列(Message Queue),依次循环。

      

Message与Handler

    那么我们在开发过程中遇到的耗时操作是如何处理的呢?

     · 这里就用到handle了,首先Handle 对象调用sendMessage 向我们的Messagequeue里面插入一条消息。

     · 当looper读取到这条消息的时候,looper又调用Handler的对象来调用 dispartchMessage 和handleMessage,

      值得注意的是 dispatchMessage通常是系统使用的,我们自己定义的Messag消息处理通常是利用                               handleMessage

     · 对消息队列的响应操作只能通过Handle来进行,主线的looper发现MessageQueue改变就回去响应消息

     · 那个Handle发的消息就有那个handle来响应

                                                         


 ·Handler中的常用方法:

                           

                           

  

 简单的例子:


package com.example.chenzhu.myprojectblog;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MyHandleActivity extends AppCompatActivity { Handler handler = new Handler(){     //接受消息并且处理消息     @Override     public void handleMessage(Message msg) {         super.handleMessage(msg);         Toast.makeText(MyHandleActivity.this, "handle Message What="+msg.what, Toast.LENGTH_SHORT).show();     } };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_my_handle);        Button button = (Button)findViewById(R.id.sendHandle);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Message msg  =  new Message();//建立一个消息                msg.what=1;                handler.sendMessage(msg);//发送一个消息            }        });    }}

Thread与Handler

        然而在主线程,如果looper在messagequeue里面读取到一个耗时操作或者死循环消息,然后还是会交给Handle  对象调用dispatchMessage来处理这个消息。而此时我们在次通过Handle 网MessageQueue里面发送一条消息          Looper读取到后有交给Handle对象处理,而此时系统还在处理上一个耗时操作。那么会怎样呢??     著名的ANR就来了,所以我们可以得到一下结论。   

         

          · Handler的sendMessage可以在其他线程中运行(本身并不需要刷新界面,只需要发送消息)

          · 耗时操作又必须在其他线程中运行。

         · 所以耗时操作在子线程完成后通过handle发送message通知主线程来完成UI线程更新UI。

 




 我们在上面的例子上在进一步进行简单的升级:

package com.example.chenzhu.myprojectblog;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MyHandleActivity extends AppCompatActivity { Handler handler = new Handler(){     //接受消息并且处理消息     @Override     public void handleMessage(Message msg) {         super.handleMessage(msg);         if (msg.what==1) {             Toast.makeText(MyHandleActivity.this, "耗时操作开始" + msg.what, Toast.LENGTH_SHORT).show();         }else {             Toast.makeText(MyHandleActivity.this, "耗时操作结束可以更新UI" + msg.what, Toast.LENGTH_SHORT).show();         }         } };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_my_handle);        Button button = (Button)findViewById(R.id.sendHandle);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Message msg  =  new Message();//建立一个消息                msg.what=1;                handler.sendMessage(msg);//发送一个消息                new  MyTheard().start();            }        });    }    //模拟耗时操作    class  MyTheard extends  Thread{        @Override        public void run() {            super.run();            try {                sleep(5);                //模拟耗时操作结束 发送消息                Message msg  =  new Message();                msg.what=2;                handler.sendMessage(msg);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
















1 0