ICode9

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

Handler工作原理之学习Handler的用法及原理笔记(一)

2021-11-16 14:30:35  阅读:116  来源: 互联网

标签:用法 Handler 线程 Looper new msg 原理 Message


前言:

        之前写过一篇博客,大概的讲了一下自己手写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;
    }

标签:用法,Handler,线程,Looper,new,msg,原理,Message
来源: https://blog.csdn.net/chirchillhe/article/details/121337219

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

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

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

ICode9版权所有