Android——子线程发消息给主线程进行页面信息更新

发布时间 2024-01-06 18:53:53作者: 小白龙白龙马

一、认识Looper和Handler对象

  当主线程诞生时,就会去执行一个消息循环(Message Loop),以便持续监视它的消息队列(Message Queue简称MQ)。

 

当UI事件发生了,通常会立即丢一个Message给MQ,此时主线程就立即从MQ里边取出该消息并处理。

 

比如,用户在UI界面上按下一个Button按钮时,UI事件发生了,就会丢一些消息到MQ里,其中包括onClick消息,于是,主线程会及时从MQ取出onClick消息,然后调用Activity的onClick()函数去处理。

 

处理完毕后,主线程又返回去继续执行消息循环,继续监视MQ,并一直循环下去,直到主线程的生命周期结束。通常是进程被删除时,主线程才会被删除。

 

 

 

 

 

Android里有一个Looper类,其对象里含有一个消息循环。也就是说,一个主线程有它自己专属的Looper对象,此线程诞生时,就会执行此对象里的消息循环。此外,一个主线程还会有其专属的MQ数据结构。

 

由于主线程会持续监视MQ的动态,所以在程序的任何函数,只要将消息丢入主线程的MQ里,就能与主线程通信了。

 

在Android,定义了一个Handler类,在程序的任何函数里,可以诞生Handler对象来将Message对象丢到MQ里,而与主线程通信。

 

在Android默认情况下,主线程诞生时,就会拥有自己的Looper对象和MQ数据结构。

 

然而,主线程诞生子线程时,默认情况下,子线程并不具有自己的Looper和MQ。

 

由于没有Looper对象,就没有消息循环(Message Loop),一旦工作完毕了,子线程就结束了,无法继续监视MQ,也就不需要MQ了。

 

既然没有Looper对象也没有MQ,也就不能接受外部的Message对象了。则别的线程就无法透过MQ来传递消息给它了。

 

也就是说,如果别的线程(如主线程)需要跟子线程相互通信时,就必须替子线程诞生一个Looper对象和一个MQ数据结构,并通过Handler来发送和处理消息。

 

 

 

 

 

xml文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvid"
        android:textSize="40sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

 

 

 

 

 

主:

package com.example.myapplication;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.Bundle;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private TextView tvObj;

    private Handler handler;

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

        tvObj = (TextView) findViewById(R.id.tvid);

        handler = new Handler(Looper.getMainLooper()) {    //表名是主线程的looper
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                tvObj.setText(String.valueOf(msg.arg1));

            }
        };

        new Thread(new Runnable() {
            @Override
            public void run() {
                int num = 0;

                while (true) {
                    Message message = Message.obtain();
                    message.arg1 = num;

                    handler.sendMessage(message);

                    SystemClock.sleep(1000);
                    num = ++num;
                }
            }
        }).start();

    }


}