zoukankan      html  css  js  c++  java
  • Android笔记(三十) Android中线程之间的通信(二)Handler消息传递机制

    什么是Handler

             之前说过了,Android不允许主线程(MainThread)外的线程(WorkerThread)去修改UI组件,但是又不能把所有的更新UI的操作都放在主线程中去(会造成ANR),那么只能单独启动一个子线程(WorkerThread)去处理,处理完成之后,将结果通知给UI主线程,子线程和主线程的通信就用到了Handler。

    Handler、Looper和MessageQueue的基本原理

             先看一下他们的职责:

             Handler——处理者,负责发送以及处理Message。

             MessageQueue——消息队列,用来存放Handler发送过来的消息,采用FIFO(first in first out)规则将Message以链表的方式串联起来的,等待Looper的抽取。

             Looper——消息泵,不断的从消息队列中取出消息并回传给Handler

             1. Handler对象调用obtainMessage()方法获取Message对象

             2. 调用sendMessage(Message msg)方法将消息发送到消息队列(MessageQueue)中

             3. Looper循环这从消息队列中取出msg

             4. 调用Handler对象的handleMessage(Message msg)方法,将取出的msg传给Handler

             Handler将消息传到队列,Looper从队列中拿到消息,然后又传给了Handler,这似乎是一个无用功,我们通过代码来看一下。

    package cn.lixyz.handlertest;
    
    import android.app.Activity;
    import android.graphics.drawable.BitmapDrawable;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    /**
     * 实现点击按钮,开始播放幻灯片,每张幻灯片间隔2s。
     */
    
    public class MainActivity extends Activity {
        
        private Button button;
        private Handler handler;   
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            button = (Button) findViewById(R.id.button);       
    
            handler = new MyHandler();
    
            button.setOnClickListener(new ButtonOnClickListener());
    
        }
        
        class ButtonOnClickListener implements View.OnClickListener {
    
            @Override
            public void onClick(View v) {
                Thread t = new ChangePicThread();
                t.start();
            }
        }
        
        class ChangePicThread extends Thread {
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(1 * 1000);
                    Log.d("TTTTT", "---->" + Thread.currentThread().getName());
                    Message msg = handler.obtainMessage();
                    msg.what = 100;
                    handler.sendMessage(msg);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        //创建内部类,继承Handler,用来创建Handle对象
        class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d("TTTTT", "====>" + Thread.currentThread().getName());
                int i = msg.what;
                Log.d("TTTTT", "message=" + i);
            }
        }
    }
    MainActivity.java
    <LinearLayout 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:orientation="vertical"
        tools:context=".MainActivity">
    
        
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="30dp"
            android:text="sendMessage" />
    
    </LinearLayout>
    activity_main.xml

             点击按钮,查看log

    09-16 10:55:12.064  12614-12669/cn.lixyz.handlertest D/TTTTT﹕ ---->Thread-213
    09-16 10:55:12.064  12614-12614/cn.lixyz.handlertest D/TTTTT﹕ ====>main
    09-16 10:55:12.064  12614-12614/cn.lixyz.handlertest D/TTTTT﹕ message=100

             可以看到,ChangePicThread的线程名是Thread-213,MyHandler的线程名是main,那message也传递过来了,那我们不就可以在线程中将所需要处理的内容处理好,将结果传给Handler,由Handler去修改UI么

    一个简单的Handler例子

             点击按钮,开始播放幻灯片。

    package cn.lixyz.handlertest;
    
    import android.app.Activity;
    import android.graphics.drawable.BitmapDrawable;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    /**
     * 实现点击按钮,开始播放幻灯片,每张幻灯片间隔2s。
     */
    
    public class MainActivity extends Activity {
    
        private ImageView imageView;
        private Button button;
        private Handler handler;
        private int[] images = {R.drawable.pic1,
                R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6,};
        private int index = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            button = (Button) findViewById(R.id.button);
            imageView = (ImageView) findViewById(R.id.imageView);
    
            handler = new MyHandler();
    
            button.setOnClickListener(new ButtonOnClickListener());
    
        }
    
        //创建内部类,实现OnClickListener接口,用于注册监听按钮开始事件
        class ButtonOnClickListener implements View.OnClickListener {
    
            @Override
            public void onClick(View v) {
                Thread t = new ChangePicThread();
                t.start();
            }
        }
    
        //创建内部类,用户执行2s变换幻灯片
        class ChangePicThread extends Thread {
            @Override
            public void run() {
                super.run();
                try {
    
                    while (true) {
                        Object obj = new Object();
                        synchronized (obj) {
                            Message msg = handler.obtainMessage();
                            msg.obj = index;
                            handler.sendMessage(msg);
                            index++;
                            Thread.sleep(2 * 1000);
                            if (index >= images.length ) {
                                index = 0;
                            }
                        }
                    }
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        //
        class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                int i = (int) msg.obj;
                BitmapDrawable bd = (BitmapDrawable) imageView.getDrawable();
                if (bd != null && !bd.getBitmap().isRecycled()) {
                    bd.getBitmap().recycle();
                }
                imageView.setImageResource(images[i]);
            }
        }
    }
    MainActivity.java
    <LinearLayout 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:orientation="vertical"
        tools:context=".MainActivity">
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="30dp"
            android:text="点击播放" />
    
    </LinearLayout>
    activity_main.xml
  • 相关阅读:
    实验三-并发程序 20175201张驰
    20175201 20175215 20175229 实验二 固件程序设计
    20175201 20175215 20175229 实验一 开发环境的熟悉
    #20175201 实验五 网络编程与安全
    云班课选做
    2019-2020-12 20175313 20175328 20175329 实验五 通讯协议设计
    2019-2020-1 20175313 20175328 20175329 实验四 外设驱动程序设计
    2019-2020-1 20175313 20175328 20175329 实验三 并发程序
    20175329&20175313&20175318 2019-2020 《信息安全系统设计基础》实验三
    20175329&20175313&20175318 2019-2020 《信息安全系统设计基础》实验二
  • 原文地址:https://www.cnblogs.com/xs104/p/4814858.html
Copyright © 2011-2022 走看看