IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Handler工作原理之学习Handler的用法及原理笔记(一) -> 正文阅读

[移动开发]Handler工作原理之学习Handler的用法及原理笔记(一)

前言:

? ? ? ? 之前写过一篇博客,大概的讲了一下自己手写Handler的一些总结和重要代码,但是总觉得有所欠缺,除了自己能看懂,别人都看不明白写了些啥,所以,决定重写写一次,从Handler的用法开始。

Handler学习笔记

什么是Handler?

? ? ? ? 用于处理异步消息的工具。工作线程通过Handler发送消息到消息队列MessageQueue,Looper会去轮询MessageQueue消息队列,取出Message,然后交给Handler分发消息,处理消息。

为什么要用Handler?

? ? ? ? Android中,规定只有主线程能操作UI,那么对于异步处理UI的情况,就需要使用主线程的Handler来进行处理子线程发送的消息。

Handler的用法?

1.Handler.sendMessage(),

? ? 根据创建Handler方式的不同有两种写法,一种是新建Handler子类继承自Handler重写HandleMessage(Message msg)方法对消息进行处理,另一种是匿名内部类方式重写HandleMessage(Message?msg)方法对消息进行处理

? ? ? ? UI布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_handler_1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:gravity="center"
        android:textSize="20sp"
        />

</LinearLayout>

? ? ? ? 1)新建Handler子类方式

package com.example.handlertest3;

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

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


    private Handler handler;
    //TextView控件
    private TextView tvHandler;

    //新建子类Handler继承Handler,重写handleMessage(Message msg)方法处理消息
    class MHandler extends Handler{
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what){
                case 1:
                    tvHandler.setText(msg.obj.toString());
                    break;
                case 2:
                    tvHandler.setText(msg.obj.toString());
                    break;
                    default:
                        break;
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //找到TextView控件
        tvHandler = findViewById(R.id.tv_handler_1);
        //top1 在主线程创建Handler实例
        handler = new MHandler();

        //top2 new Thread方式创建子线程1,发送message消息到消息队列,并且指定操作的UI内容
        new Thread(){
            //重写run()方法,在run()方法里面实现要实现的逻辑功能
            @Override
            public void run() {
                try {
                    //子线程休眠3秒
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //实例化消息对象
                Message msg = Message.obtain();
                //消息标识
                msg.what = 1;
                //消息内容
                msg.obj = "执行了子线程1的UI操作";

                //发送消息到消息队列MessageQueue
                handler.sendMessage(msg);
            }
        }.start();
        //new Runnable方式创建子线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //线程休眠3秒
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //实例化消息对象
                Message msg = Message.obtain();
                //消息标识
                msg.what = 2;
                //消息内容
                msg.obj = "执行了线程2的UI操作";

                //发送消息到消息队列MessageQueue
                handler.sendMessage(msg);
            }
        }).start();
    }
}

? ? ? ? 2)匿名内部类方式

package com.example.handlertest3;

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

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


    private Handler handler;
    //TextView控件
    private TextView tvHandler;

/*    //新建子类Handler继承Handler,重写handleMessage(Message msg)方法处理消息
    class MHandler extends Handler{
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what){
                case 1:
                    tvHandler.setText(msg.obj.toString());
                    break;
                case 2:
                    tvHandler.setText(msg.obj.toString());
                    break;
                    default:
                        break;
            }
        }
    }*/

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //找到TextView控件
        tvHandler = findViewById(R.id.tv_handler_1);
        //top1 在主线程创建Handler实例
        /*handler = new MHandler();*/
        //通过匿名内部类方式创建Handler实例并重写handlMessage(Message msg)方法处理消息
        handler = new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                switch (msg.what){
                    case 1:
                        tvHandler.setText(msg.obj.toString());
                        break;
                    case 2:
                        tvHandler.setText(msg.obj.toString());
                        break;
                }
            }
        };

        //top2 new Thread方式创建子线程1,发送message消息到消息队列,并且指定操作的UI内容
        new Thread(){
            //重写run()方法,在run()方法里面实现要实现的逻辑功能
            @Override
            public void run() {
                try {
                    //子线程休眠3秒
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //实例化消息对象
                Message msg = Message.obtain();
                //消息标识
                msg.what = 1;
                //消息内容
                msg.obj = "执行了子线程1的UI操作";

                //发送消息到消息队列MessageQueue
                handler.sendMessage(msg);
            }
        }.start();
        //new Runnable方式创建子线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //线程休眠3秒
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //实例化消息对象
                Message msg = Message.obtain();
                //消息标识
                msg.what = 2;
                //消息内容
                msg.obj = "执行了线程2的UI操作";

                //发送消息到消息队列MessageQueue
                handler.sendMessage(msg);
            }
        }).start();
    }
}

2.Handler.postMessage()

package com.example.testhandlerpost;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView tvPostHandler;
    private Handler mHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //找到TextView控件
        tvPostHandler = findViewById(R.id.tv_post_handler);
        //在主线程创建Handler实例
        mHandler = new Handler();

        new Thread(){
            @Override
            public void run() {
                try {
                    //线程1休眠3秒
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //通过Handler.Post()发送消息到消息队列,需要一个Runnable对象
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        tvPostHandler.setText("执行了线程1的UI操作");
                    }
                });
            }
        }.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //线程2休眠6秒
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        tvPostHandler.setText("执行了线程2的UI操作");
                    }
                });
            }
        }).start();
    }
}

Handler的基本原理

? ? ? ? 1.创建主线程的时候,会自动调用ActivityThread.java类中的main()方法,在main()方法中,调用了Looper.prepareMainLooper()生成一个Looper对象,同时生成一个MessageQueue对象。同时在ActivityThread中开启了Loop.loop消息循环。

#ActivityThread.java


public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // Install selective syscall interception
        AndroidOs.install();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        // Call per-process mainline module initialization.
        initializeMainlineModules();

        Process.setArgV0("<pre-initialized>");

        //创建主线程的时候生成Looper对象同时生成了MessageQueue对象
        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();//-------创建主线程-------------!!!!
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();//------------------自动开启消息循环--------------------------!!!

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
#Looper.prepareMainLooper()

   @Deprecated
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
#Looper.prepare(boolean quitAllowed)
  
 private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
#Loopr.Looper(boolean quitAllowed)构造方法,在创建Looper对象的同时,也生成了MessageQueue对象    

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
 /**
     * 获取当前线程的Looper对象,如果调用线程没有与Looper进行关联,那么返回null
     */
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

我们在使用的时候,会在主线程创建一个Handler对象,重写handleMessage(Message?msg)方法对Looper.loop在MessageQueue消息队列轮询取出的消息进行分发,处理。

  @Deprecated
    public Handler() {
        this(null, false);
    }
public Handler(@Nullable Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
        
        //获取当前线程的Looper对象
        //如果当前线程的Looper对象为空,抛出异常
        //所以如果需要在子线程创建Handler对象,需要先创建Looper对象
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        //绑定MessageQueue对象到当前线程的Looper对象上
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-17 12:52:17  更:2021-11-17 12:54:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:29:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码