Android中Handler传递消息机制详解

欢迎转载,但请标明出处:http://blog.csdn.net/android_for_james/article/details/51173944

如果有多个线程并发操作UI,就有可能会导致线程安全问题,为了解决这个问题,Android制定了一个规则:只允许UI线程修改Activity里的UI,如果我们想动态的改变界面组件的属性值就需要用到Handler。例如我们在执行下载图片任务时,显然这是一个耗时任务,我们需要一个新线程来完成这个下载任务,当任务完成后我们需要将图片绘制到界面上,这时就需要Hanlder来发送一个消息给ImageView告诉它需要绘制图片。

我们先来看一下我这个例子程序的运行效果图:

首先我们需要知道Handler,Looper,MessageQueue这三者是做什么的

1.Handler:它具有两个功能,一个是发消息和处理消息。

2.Looper:它是一个循环器,作用是用来循环取出MessageQueue中的消息。

3.MessageQueue:它是一个消息队列,既然是队列当然具有先进先出原则,用来管理Message。

三者的关系是:

Handler发送消息给----->MessageQueue(不过MessageQueue是由Looper来管理的,因此在做这步操作时,在线程应该已经有一个Looper对象)----->Looper(循环读取MessageQueue中的Message)----->Handler(处理Looper读取到的消息)

这里我们不禁会产生疑问,我们在主线程中使用Handler时并没有涉及到MessageQueue和Looper呀~我们知道他们之间的关系干什么?

这个问题的答案就是在主UI线程中,系统已经为我们初始化了一个Looper对象了,因此我们直接创建Handler对象即可发送消息,还有一个需要我们知道的是,每一个线程都只有一个与之对应的Looper,因此当我们自己的线程类中新建的Handler发送消息时就不能使用主线程中的Looper,那么这时我们的线程类就需要一个自己的Looper。

解决上述问题的方法是:

class MyThread extends Thread
    {
        public Handler myhandler;
        @Override
        public void run() {
            super.run();
            //创建该线程的Looper对象
            Looper.prepare();
            myhandler=new Handler()
            {
                @Override
                public void handleMessage(Message msg) {
                  
                    super.handleMessage(msg);
         
                }
            };
            //循环器开始循环
            Looper.loop();
        }
    }
我来介绍一下我这个例子程序有什么内容

1.介绍了Handler的四种发送消息的用法分别是:

(1)post()

(2)postDelayed()(实现图片动态循环显示)

(3)sendMessage()

(4)sendEmptyMessage()

2.在线程类中新建自己的Handler并在主线程中调用

布局文件很简单,就是两个TextView一个ImageView所以我就不给布局代码了

下面我们来看具体代码:

public class MainActivity extends ActionBarActivity {

    private ImageView image;

    private TextView text;
    private TextView text2;

    private int images[]={R.drawable.a1,R.drawable.a2,R.drawable.a3};
    private int index=0;

    private MyRunnable myRunnable=new MyRunnable();

    private MyThread zyThread;
    private Handler handler=new Handler();

    private Handler handler2=new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Toast.makeText(MainActivity.this,msg.obj.toString(),Toast.LENGTH_LONG).show();
        }
    };

    //要想使用handler的postDelayed()方法必须有一个runnable对象
    class MyRunnable implements Runnable
    {
        @Override
        public void run() {
            index++;
            index=index%images.length;
            image.setImageResource(images[index]);
            text.setText("第"+(index+1)+"张图片");
            handler.postDelayed(myRunnable,1500);
        }
    }
    class MyThread extends Thread
    {
        public Handler myhandler;
        @Override
        public void run() {
            super.run();
            //创建该线程的Looper对象
            Looper.prepare();
            myhandler=new Handler()
            {
                @Override
                public void handleMessage(Message msg) {
                  
                    super.handleMessage(msg);
                    Toast.makeText(MainActivity.this,"新线程tdhandler中的message信息是"+msg.obj.toString(),Toast.LENGTH_LONG).show();
                }
            };
            //循环器开始循环
            Looper.loop();
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initEvent();
        //使用postDelayed()发送数据,这时数据会根据后面的值延迟
        handler.postDelayed(myRunnable, 1500);
        //启动新线程
        zyThread=new MyThread();
        zyThread.start();
        try {
            zyThread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //在新线程中使用线程自己的handler发送数据
        Message message2=new Message();
        message2.obj="我是tdThread线程中的message";
        zyThread.myhandler.sendMessage(message2);

        new Thread()
        {
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(1000);
                    //直接使用post发送数据
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            text2.setText("使用post方法更新数据");
                        }
                    });
                    //使用sendmessage发送数据
                    Message message=new Message();
                    message.obj="使用sendmessage发送数据";
                    handler2.sendMessage(message);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }
    public void initEvent()
    {
        image=(ImageView)findViewById(R.id.imageView);
        text=(TextView)findViewById(R.id.textView);
        text2=(TextView)findViewById(R.id.textView2);
    }


}
依然是在最后我用红字标出需要注意的问题

1.在新线程中创建Handler时必须先创建Looper,即先调用Looper.prepare()为当前线程创建一个Looper实例,并创建配套的MessageQueue,再去创建Handler对象,最后调用
Looper.loop来开始循环读取消息

2.handleMessage方法一般用于重写操作

希望对大家有所帮助,欢迎转载但要标明出处,谢谢!!!

有什么不足的地方可以留言给我我会尽快回复并改正!!!

欢迎关注我的博客:http://blog.csdn.net/android_for_james






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值