Android Handler例程(sendMessage与post)

handler的应用场景

在安卓中,只有主线程才能进行UI操作。说明子线程内无法实现对UI的修改,因此安卓必然支持一种线程通信机制,使得子线程可以发消息让主线程改一下UI,该方案就是handler。

安卓中子线程之间也需要通信,通信方案也是handler。

消息机制

该通信机制分为四个部分:

message:线程中用来传递的信息载体。

messagequeue:存放消息的队列。通信机制是异步的,也就是说存放消息与取消息是独立的操作,本质上是一种生产者-消费者模式。

handler:接收器与发送器的实现。可以理解为是手机,手机可以发消息,也可以收消息。

looper:消息队列的循环调度器,负责将消息队列里面的消息自动分发给对应的接收器。

全部代码1

package com.example.handlertest;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = findViewById(R.id.text1);

        //匿名内部类创建Handler对象
        handler = new Handler(){
            //重写handleMessage函数对收到的消息进行处理
            @Override
            public void handleMessage(Message message){
                switch (message.what){//根据消息标识进行处理
                    case 1:
                        textView.setText("Thread 1!");
                        break;
                    case 2:
                        textView.setText("Thread 2!");
                        break;
                    default:
                        break;
                }
            }
        };

        //创建新的子线程1
        new Thread(){
            @Override
            public void run(){
                try {
                    //延时
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //创建消息对象
                Message message = Message.obtain();
                //设定消息标识
                message.what = 1;
                //通过handler将消息发送到消息队列中
                handler.sendMessage(message);
            }
        }.start();//开启线程


        //创建新的子线程2
        new Thread(){
            @Override
            public void run(){
                try {
                    //延时,和线程1错开
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //创建消息对象
                Message message = Message.obtain();
                //设定消息标识
                message.what = 2;
                //通过handler将消息发送到消息队列中
                handler.sendMessage(message);
            }
        }.start();//开启线程
    }
}

通过两个线程先后发送消息,改变界面里文字的输出。

需要注意的是两个线程本身只执行一次,文字改变只有两次。

代码讲解

代码中存在三个线程,主线程以及自己设定的两个子线程。

private Handler handler;

但是handler对象只需要创建一个,因为进程内部的多个线程是共享内存的,三个线程用的是同一个handler实例。

扫描二维码关注公众号,回复: 14969626 查看本文章

本文的代码使用匿名内部类重写handler对象里收到信息后的处理函数handleMessage:


        //匿名内部类创建Handler对象
        handler = new Handler(){
            //重写handleMessage函数对收到的消息进行处理
            @Override
            public void handleMessage(Message message){
                switch (message.what){//根据消息标识进行处理
                    case 1:
                        textView.setText("Thread 1!");
                        break;
                    case 2:
                        textView.setText("Thread 2!");
                        break;
                    default:
                        break;
                }
            }
        };

该实例在主线程中创建,因此处理函数是在主线程进行的,可以进行UI修改。

也可以不使用匿名内部类,直接定义一种Handler的子类,并在主线程中创建一个对象。在该类的定义中实现对消息处理函数的重写。

                //创建消息对象
                Message message = Message.obtain();
                //设定消息标识
                message.what = 1;
                //通过handler将消息发送到消息队列中
                handler.sendMessage(message);

在子线程中只需要创建一个消息对象,设置消息内容,并发送到消息队列中即可。

消息队列messagequeue和循环控制器looper对开发者来说是隐式存在的,程序中仅体现了发送与接收的过程。

全部代码2

使用post的方式如下所示:

package com.example.handlertest2;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    public TextView mTextView;
    public Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.text1);

        mHandler = new Handler();

        //第一个工作线程
        new Thread(){
            @Override
            public void run(){
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //传入runnable对象进行发送
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mTextView.setText("Thread 1!");
                    }
                });
            }
        }.start();

        //第二个工作线程
        new Thread(){
            @Override
            public void run(){
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mTextView.setText("Thread 2!");
                    }
                });
            }
        }.start();
    }
}

第二种方法可以不对Handler进行重写,只需要调用其post方法即可。

猜你喜欢

转载自blog.csdn.net/m0_37872216/article/details/126348676
今日推荐