您的位置:首页 > 移动开发 > Android开发

Android之Handler消息机制

2016-03-02 16:00 483 查看

android中Handle类的主要作用:

  1.在新启动的线程中发送给消息

  2.在主线程获取、处理消息

欢迎加入QQ交流3群:317874559

为什么要用Handle这样的一个机制:

  因为在Android系统中UI操作并不是线程安全的,如果多个线程并发的去操作同一个组件,可能导致线程安全问题。为了解决这一个问题,android制定了一条规则:只允许UI线程来修改UI组件的属性等,也就是说必须单线程模型,这样导致如果在UI界面进行一个耗时叫长的数据更新等就会形成程序假死现象 也就是ANR异常,如果20秒中没有完成程序就会强制关闭。所以比如另一个线程要修改UI组件的时候,就需要借助Handler消息机制了。

Handle发送和处理消息的几个方法:

  1. void  handleMessage( Message  msg):处理消息的方法,该方法通常被重写。

   2.final boolean hasMessage(int  what):检查消息队列中是否包含有what属性为指定值的消息

   3.final boolean hasMessage(int what ,Object object) :检查消息队列中是否包含有what好object属性指定值的消息

   4.sendEmptyMessage(int what):发送空消息

    5.final Boolean send EmptyMessageDelayed(int what ,long delayMillis):指定多少毫秒发送空消息

    6.final  boolean sendMessage(Message msg):立即发送消息

    7.final boolean sendMessageDelayed(Message msg,long delayMillis):多少秒之后发送消息

与Handle工作的几个组件Looper、MessageQueue各自的作用:

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

   2.MessageQueue:采用先进的方式来管理Message

   3.Looper:每个线程只有一个Looper,比如UI线程中,系统会默认的初始化一个Looper对象,它负责管理MessageQueue,不断的从MessageQueue中取消息,并将

                    相对应的消息分给Handler处理

在线程中使用Handler的步骤:

 1.调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会自动的创建相对应的MessageQueue

  2.创建Handler子类的实例,重写HandleMessage()方法,该方法处理除UI线程以外线程的消息

  3.调用Looper的loop()方法来启动Looper

实例



[html]
view plain
copy
print?

<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" >  
  
    <EditText  
        android:id="@+id/ed1"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:inputType="number" />  
  
    <Button  
        android:id="@+id/Ok"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_below="@id/ed1"  
        android:text="@string/Ok" />  
  
  
    <Button  
        android:id="@+id/next"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_below="@id/Ok"  
        android:text="下一张" />  
  
    <ImageView  
        android:id="@+id/image1"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:layout_below="@id/next"  
        android:src="@drawable/a3" />  
  
</RelativeLayout>  

<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" >

<EditText
android:id="@+id/ed1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />

<Button
android:id="@+id/Ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ed1"
android:text="@string/Ok" />

<Button
android:id="@+id/next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/Ok"
android:text="下一张" />

<ImageView
android:id="@+id/image1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/next"
android:src="@drawable/a3" />

</RelativeLayout>


[java]
view plain
copy
print?





package com.android.xiong.handlertesttwo;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.os.Handler;  
import android.os.Looper;  
import android.os.Message;  
import android.view.Menu;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.ImageView;  
import android.widget.TextView;  
import android.widget.Toast;  
  
public class MainActivity extends Activity {  
    //吗的 不知怎么的Toast显示的是好像一定要点下图片 显示的才能在屏幕上看到效果  
    private EditText ed1;  
    private Button ok1;  
    private Button next;  
    private ImageView image1;  
    private Thread th;  
    private  static int s=1;  
    private int iamges[] = { R.drawable.a3, R.drawable.a4 };  
  
    private final String DATA = "data";  
  
    // 实现Runnable接口  
    class Rub implements Runnable {  
  
        public Handler myHandler;  
        // 线程体  
        @Override  
        public void run() {  
  
            Looper.prepare();  
             myHandler = new Handler() {  
                @Override  
                public void handleMessage(Message msg) {  
                    String ms = "";  
                    if (msg.what == 0x123) {  
                        int data = msg.getData().getInt(DATA);  
                        //循环的时候界面依旧可以点击next按钮 这是本实例效果  
                        for (int i = 0; i < data; i++) {  
                            try {  
                                //循环一次 暂停1秒  
                                Thread.sleep(500);  
                            } catch (InterruptedException e) {  
                                e.printStackTrace();  
                            }  
                            ms += String.valueOf(i) + "  ";  
                            Toast.makeText(getApplicationContext(), ms, Toast.LENGTH_LONG)  
                            .show();  
                              
                        }  
                  
                    }  
                }  
  
            };  
            Looper.loop();  
        }  
  
    }  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        ed1 = (EditText) findViewById(R.id.ed1);  
        ok1 = (Button) findViewById(R.id.Ok);  
        next = (Button) findViewById(R.id.next);  
        image1 = (ImageView) findViewById(R.id.image1);  
  
        final Rub rub = new Rub();  
        //子线程中不能有UI组件进行操作   
        th = new Thread(rub);  
        // 启动线程  
        th.start();  
        ok1.setOnClickListener(new OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                Message msg = new Message();  
                msg.what = 0x123;  
                Bundle bundle = new Bundle();  
                bundle.putInt(DATA, Integer.parseInt(ed1.getText().toString()));  
                msg.setData(bundle);  
                rub.myHandler.sendMessage(msg);  
                  
            }  
        });  
        //在UI线程中操作组件  
        next.setOnClickListener(new OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                image1.setImageResource(iamges[s++% iamges.length] );  
            }  
        });  
    }  
  
    @Override  
    public boolean onCreateOptionsMenu(Menu menu) {  
        // Inflate the menu; this adds items to the action bar if it is present.  
        getMenuInflater().inflate(R.menu.main, menu);  
        return true;  
    }  
  
}  

package com.android.xiong.handlertesttwo; 

 

import android.app.Activity; 

import android.os.Bundle; 

import android.os.Handler; 

import android.os.Message; 

import android.view.Menu; 

import android.view.View; 

import android.view.View.OnClickListener; 

import android.widget.Button; 

import android.widget.EditText; 

import android.widget.ImageView; 

import android.widget.Toast; 

 

public class MainActivity extends Activity { 

    //吗的 不知怎么的Toast显示的是好像一定要点下图片 显示的才能在屏幕上看到效果 

    private EditText ed1; 

    private Button ok1; 

    private Button next; 

    private ImageView image1; 

  

    private  static int s=1; 

    private int iamges[] = { R.drawable.a3, R.drawable.a4 }; 

 

    private final String DATA = "data"; 

    public Handler myHandler;

   

 

 

    @Override 

    protected void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.activity_main); 

        ed1 = (EditText) findViewById(R.id.ed1); 

        ok1 = (Button) findViewById(R.id.Ok); 

        next = (Button) findViewById(R.id.next); 

        image1 = (ImageView) findViewById(R.id.image1); 

 

        myHandler = new Handler() { 

            @Override 

            public void handleMessage(Message msg) { 

                String ms = ""; 

                if (msg.what == 0x123) { 

                    int data = msg.getData().getInt(DATA); 

                    //循环的时候界面依旧可以点击next按钮 这是本实例效果 

                    for (int i = 0; i < data; i++) { 

                        try { 

                            //循环一次 暂停1秒 

                            Thread.sleep(500); 

                        } catch (InterruptedException e) { 

                            e.printStackTrace(); 

                        } 

                        ms += String.valueOf(i) + "  "; 

                        Toast.makeText(getApplicationContext(), ms, Toast.LENGTH_LONG) 

                        .show(); 

                         

                    } 

             

                } 

            } 

        };

       

        ok1.setOnClickListener(new OnClickListener() { 

 

            @Override 

            public void onClick(View v) { 

                Message msg = new Message(); 

                msg.what = 0x123; 

                Bundle bundle = new Bundle(); 

                bundle.putInt(DATA, Integer.parseInt(ed1.getText().toString())); 

                msg.setData(bundle); 

                myHandler.sendMessage(msg); 

                 

            } 

        }); 

        //在UI线程中操作组件 

        next.setOnClickListener(new OnClickListener() { 

             

            @Override 

            public void onClick(View v) { 

                image1.setImageResource(iamges[s++% iamges.length] ); 

            } 

        }); 

    } 

 

    @Override 

    public boolean onCreateOptionsMenu(Menu menu) { 

        // Inflate the menu; this adds items to the action bar if it is present. 

        getMenuInflater().inflate(R.menu.main, menu); 

        return true; 

    } 

 



其实Handler不仅可以更新UI,你完全可以在一个子线程中去创建一个Handler,然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。

[java]
view plain
copy
print?





new Thread()  
        {  
            private Handler handler;  
            public void run()  
            {  
  
                Looper.prepare();  
                  
                handler = new Handler()  
                {  
                    public void handleMessage(android.os.Message msg)  
                    {  
                        Log.e("TAG",Thread.currentThread().getName());  
                    };  
                };
Looper.loop();
}  

new Thread()
{
private Handler handler;
public void run()
{

Looper.prepare();

handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
Log.e("TAG",Thread.currentThread().getName());
};
};<div class="dp-highlighter bg_java"><div class="bar"><div class="tools"><strong>[java]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.csdn.net/lmj623565791/article/details/38377229#">view plain</a><span class="tracking-ad" data-mod="popu_168"> <a target=_blank title="copy" class="CopyToClipboard" href="http://blog.csdn.net/lmj623565791/article/details/38377229#" target="_blank">copy</a></span><span class="tracking-ad" data-mod="popu_169"> <a target=_blank title="print" class="PrintSource" href="http://blog.csdn.net/lmj623565791/article/details/38377229#" target="_blank">print</a></span><a target=_blank title="?" class="About" href="http://blog.csdn.net/lmj623565791/article/details/38377229#">?</a><span class="tracking-ad" data-mod="popu_167"><a target=_blank title="在CODE上查看代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/445431" target="_blank"><img width="12" height="12" style="left: 2px; top: 1px; position: relative;" alt="在CODE上查看代码片" src="https://code.csdn.net/assets/CODE_ico.png" /></a></span><span class="tracking-ad" data-mod="popu_170"><a target=_blank title="派生到我的代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/445431/fork" target="_blank"><img width="12" height="12" style="left: 2px; top: 2px; position: relative;" alt="派生到我的代码片" src="https://code.csdn.net/assets/ico_fork.svg" /></a></span></div></div><ol class="dp-j"><li class="alt"><span><span>Looper.loop();                                                                                                                              }               </span></span></li></ol></div><pre class="java" style="display: none;" name="code" snippet_file_name="blog_20140808_19_1943618" code_snippet_id="445431">                               Looper.loop();                                                                                                                              }



Android不仅给我们提供了异步消息处理机制让我们更好的完成UI的更新,其实也为我们提供了异步消息处理机制代码的参考~~不仅能够知道原理,最好还可以将此设计用到其他的非Android项目中去~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: