ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

handler机制

2022-02-23 15:02:13  阅读:195  来源: 互联网

标签:Toast handler 线程 Looper import new 机制 Message


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去添加。

标签:Toast,handler,线程,Looper,import,new,机制,Message
来源: https://blog.csdn.net/Q1ANfeng/article/details/123090147

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有