11.Android学习之Handler消息处理(一)

本文介绍了Android中Handler消息传递机制的重要性,强调了不能在子线程直接修改UI组件的规则,并详细阐述了Handler类的功能,包括在任意线程发送消息和在主线程处理消息的能力。同时,列举了Handler类的主要方法,帮助开发者更好地利用Handler进行消息操作。

目录

11.Handler消息处理(一)

1.Handler消息传递机制

1-1.Handler 类简介

1-2.Handler 类中的常用方法


11.Handler消息处理(一)

1.Handler消息传递机制

在Java中,对于一些周期性的或者是耗时的操作通常由多线程来实现,而在Android中,也可以使用Java中的多线程技术。例如,在手机淘宝主界面的上方,对广告进行轮换显示,以及某些游戏中的计时进度条,都应用了多线程技术。

在Android中使用多线程,有一点需要注意:不能在子线程中动态改变主线程中的UI组件的属性。

注:当一个程序第一次启动时,Android会启动一条主线程,用于负责接收用户的输入,将运行的结果反馈给用户,也称为UI线程;而子线程是指为了执行一些可能产生阻塞操作而新启动的线程,也称为Worker线程。

例如,实现单击按钮时创建新线程,用于改变文本框的显示文本,代码如下:

public class MainActivity extends AppCompatActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        TextView textView=findViewById(R.id.main_tv1);
        Button button=findViewById(R.id.main_btn1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //创建新线程
                Thread thread=new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //要执行的操作
                        textView.setText("你今天的努力,是幸运的伏笔;当下的付出,是明日的花开");
                    }
                });
                thread.start();//开启线程
            }
        });
    }

点击按钮后软件将停止运行,在Logcat面板中输出如图所示的异常信息。

 原因:子线程不允许操作主线程中的组件!

为此,Android中引入了Handler消息传递机制,来实现在新创建的线程中操作UI界面。

更改后成功运行:

package com.example.demo;
​
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
​
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 {
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActionBar actionBar=getSupportActionBar();
        actionBar.hide();
​
        TextView textView=findViewById(R.id.main_tv1);
        Button button=findViewById(R.id.main_btn1);
        Handler handler=new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                if(msg.what==0x123){
                    textView.setText("你今天的努力,是幸运的伏笔;当下的付出,是明日的花开");
                }
            }
        };
​
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //创建新线程
                Thread thread=new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //发送空消息
                        //what->指定消息代码,自定义就行
                        handler.sendEmptyMessage(0x123);
                    }
                });
                thread.start();
            }
        });
    }
}

注:

进程:一个Android应用就是一个进程,每个应用在各自的进程中运行。

线程:比进程更小的独立运行的基本单位,一个进程可以包含多个线程。

1-1.Handler 类简介

Handler是Android提供的一个用来更新UI的机制,也是一个消息处理的机制。通过Handler类(消息处理类)可以发送和处理Message对象到其所在线程的MessageQueue中。

Handler类主要有以下两个作用。

(1)在任意线程中发送消息

将Message应用sendMessage() 方法发送到MessageQueue中,在发送时可以指定延迟时间、发送时间以及要携带的Bundle数据。当Looper循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。

(2)在主线程中获取并处理消息

为了让主线程能在适当的时候处理Handler所发送的消息,必须通过回调方法来实现。开发者只需要重写Handler类中处理消息的方法。这样当新启动的线程发送消息时,Handler 类中处理消息的方法就会被自动回调。

1-2.Handler 类中的常用方法

在Handler类中包含了一些用于发送和处理消息的常用方法,这些方法如表11.1 所示。

表11.1 Handler 类提供的常用方法

方法描述
handleMessage(Message msg)处理消息的方法。通常重写该方法来处理消息,在发送消息时,该方法会自动回调
hasMessages(int what)检查消息队列中是否包含what属性为指定值的消息
hasMessages(int what, Object object)检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息
post(Runnable r)立即发送Runnable对象,该Runnable对象最后将被封装成Message对象
postAtTime(Runnable r, long uptimeMillis)定时发送Runnable 对象,该Runnable对象最后将被封装成Message对象
postDelayed(Runnable r, long delayMillis)延迟发送Runnable对象,该Runnable对象最后将被封装成Message对象
sendEmptyMessage(int what)发送空消息
sendEmptyMessageDelayed(int what, long delayMillis)指定多少毫秒之后发送空消息
sendMessage(Message msg)立即发送消息
sendMessageAtTime(Message msg, long uptimeMillis)定时发送消息
sendMessageDelayed(Message msg, long delayMillis)延迟发送消息
obtainMessage()获取消息

通过这些方法,应用程序就可以方便地使用Handler来进行消息传递。

例:

 MainActivity.java

package com.example.timeprogressbar;
​
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
​
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ProgressBar;
import android.widget.Toast;
​
public class MainActivity extends AppCompatActivity {
    private ProgressBar timer;//声明水平进度条
    final int TIME = 60;//定义时间长度60秒
    private int mProgressStatus = 0;//定义完成的进度
    final int TIMER_MSG = 0x001;//消息代码
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();
        timer = findViewById(R.id.main_pb1);
        //启动进度条
        handler.sendEmptyMessage(TIMER_MSG);
    }
​
    //创建Handler对象,实现1秒钟更新一次进度
    Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (TIME - mProgressStatus > 0) {//当前进度大于0
                mProgressStatus++;//进度加1
                timer.setProgress(TIME - mProgressStatus);//更新进度
                //一秒后发送消息
                handler.sendEmptyMessageDelayed(TIMER_MSG, 1000);
            } else {
                Toast.makeText(MainActivity.this, "时间到,游戏结束!", Toast.LENGTH_SHORT).show();
            }
        }
    };
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值