Android——子线程发消息给主线程进行页面信息更新
一、认识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(); } }