handler机制

handler机制


主线程中不能存在耗时操作,所有主线程会将耗时操作分配给子线程

可以通过handler来实现主线程和子线程的通信

在xml文件中进行布局

一个textview和button

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="结果"
        android:textSize="30sp"/>

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="start"
        android:onClick="start"
        tools:ignore="OnClick">

    </Button>

</LinearLayout>

通过点击事件进行通信

public void start(View view){
      Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                String strData = getData();

                Message message = new Message();
                message.what=0;
                message.obj=strData;

                mhandler.sendMessage(message);

            }
        });
        thread.start();
        Toast.makeText(MainActivity.this, "点击开始", Toast.LENGTH_SHORT).show();

}

创建一个耗时方法

public String getData(){
    
   StringBuilder sb = new StringBuilder();
    for(int i =0 ; i<100 ; i++){
        sb.append(i);
    }
    try { Thread.sleep(1000);
    }catch(InterruptedException e) {
        e.printStackTrace();
    }
       result = sb.toString();

    return result;
}

new一个handler

    private final Handler mhandler = new Handler(Looper.myLooper()){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            if (msg.what == 0){
                String strData = (String) msg.obj;

                textView.setText(strData);
                Toast.makeText(MainActivity.this, "主线程接受结果", Toast.LENGTH_SHORT).show();

            }
        }
    };

完整代码

package com.example.handletest;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    TextView textView;

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

        textView = findViewById(R.id.tv);

    }

    private final Handler mhandler = new Handler(Looper.myLooper()){     //()中有一个警告关于内存泄漏,添加一个Looper.myLooper
        @Override
        public void handleMessage(@NonNull Message msg) {    //new完handler后重写handlermessage方法
            super.handleMessage(msg);

            if (msg.what == 0){       //  通过msg.what的值进行匹配对应的子线程
                String strData = (String) msg.obj;

                textView.setText(strData);     // 将子线程运行出的结果通过主线程来设置
                Toast.makeText(MainActivity.this, "主线程接受结果", Toast.LENGTH_SHORT).show();

            }
        }
    };


    public void start(View view){

        Thread thread = new Thread(new Runnable() {     // 创建一个线程Thread 
            @Override
            public void run() {
                String strData = getData();

                Message message = new Message();     // new一个Message,处理文本
                message.what=0;
                message.obj=strData;

                mhandler.sendMessage(message);     //通过handler机制的sendMessage方法发送文本

            }
        });
        thread.start();       // 别忘记启动线程
        Toast.makeText(MainActivity.this, "点击开始", Toast.LENGTH_SHORT).show();

    }


    private String getData(){     // 写一个获取数据的耗时方法
        String result;

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i<100; i++){
            sb.append(i);
        }

        try {
            Thread.sleep(3000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

        result = sb.toString();

    return result;
    }


}

handler

使用Handler的原因:将工作线程需操作UI的消息 传递 到主线程,使得主线程可根据工作线程的需求 更新UI从而避免线程操作不安全的问题

looper

  1. Looper可以让一个线程具有循环工作的特性,也就说可以把线程编程Looper线程。

  2. 每个线程只能也最多有一个Looper对象,这个Looper对象是一个Thredlocal,可以保证当前线程操作的Looper对象一定是当前线程自己的。

  3. Looper内部又一个MQ,调用loop()方法后线程开始不断的从MQ中去消息交给后面的Handler处理。

message

Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。Message中包含了两个额外的int字段和一个object字段,这样在大部分情况下,使用者就不需要再做内存分配工作了。虽然Message的构造函数是public的,但是最好是使用Message.obtain( )或Handler.obtainMessage( )函数来获取Message对象,因为Message的实现中包含了回收再利用的机制,可以提供效率。

messageQuery

MessageQueue用来容纳Message队列的,其中的Message是由Looper来分发的,Message不能直接添加到MessageQueue中,而是要通过与Looper关联的Handler去添加。

上一篇:Vue使用mock使用教程


下一篇:【最小Demo】Java RMI入门 使用Registry、Naming、Zookeeper(注册中心)实现rmi