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;
    }
上一篇:我终于读懂了Handler


下一篇:Handler面试那些事