Handler的基本用法(源码解析 基于nate视频)

目录

相关视频:

相关文章:

一、Handler理解:(参照以上视频内容)

二、Handler的使用:

(一)、异常展示:

(二)、使用Runnable:

(三)、使用sendMessage():

(四)、使用sendMessage() 传递实体类:

三、源码解析:


相关视频:

Android面试常客Handler详解

相关文章:

Handler用法及解析

Handler的作用与用法

一、Handler理解:(参照以上视频内容)

当你创建一个新的Handler的时候,它是被一个Thread创建的,这个新的Handler会和这个Thread绑定,同时这个Handler也会被绑定到这个Thread的MessageQueue当中。

当一个Application被创建的时候,就会创建一个Main Thread,在Android中也就是ActivityThread,也就是我们常说的UI线程。

    private MyThread myThread;

    private void method5() {
        myThread = new MyThread();
        myThread.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread.handler.sendEmptyMessage(1);

        handler5.sendEmptyMessage(1);
    }

    @SuppressLint("HandlerLeak")
    private Handler handler5 = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            /**
             * 默认与UI线程进行关联
             * 因此不能做一些耗时操作
             */
            LogUtils.e("UI线程ID为:" + Thread.currentThread());
        }
    };

    /**
     * 当你创建一个新的Handler的时候,它是被一个Thread创建的,这个新的Handler会和这个Thread绑
        定,
     * 同时这个Handler也会被绑定到这个Thread的MessageQueue当中。
     * 

* 当一个Application被创建的时候,就会创建一个Main Thread,在Android中也就是 ActivityThread,也就是我们常说的UI线程。 */ class MyThread extends Thread { public Handler handler; public Looper looper; @SuppressLint("HandlerLeak") @Override public void run() { Looper.prepare(); looper = Looper.myLooper(); handler = new Handler() { @Override public void handleMessage(Message msg) { LogUtils.e("当前线程id为:" + Thread.currentThread()); } }; Looper.loop(); } }

 以下为打印结果:

二、Handler的使用:

主要方法:

sendMessage(Message msg)
sendMessageDelayed(Message msg, long delayMillis)
post(Runnable r)
postDealyed(Runnable r, long uptimeMillis)

其他方法:

obtainMessage()

post(Runnable r)
postAtTime(Runnable r, long uptimeMillis)
sendMessage(Message msg)
sendMessageDelayed(Message msg, long delayMillis)
sendMessageAtTime(Message msg, long uptimeMillis)

sendEmptyMessage(int what)
sendEmptyMessageDelayed(int what, long delayMillis)
sendEmptyMessageAtTime(int what, long uptimeMillis)

Handler的基本用法(源码解析 基于nate视频)_第1张图片

(一)、异常展示:

Handler的基本用法(源码解析 基于nate视频)_第2张图片

android.view.ViewRootImpl$CalledFromWrongThreadException:

Only the original thread that created a view hierarchy can touch its views.

代码:

new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    textView.setText("update");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

(二)、使用Runnable:

 private Handler handler1 = new Handler();

    private void method2() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    handler1.post(new Runnable() {
                        @Override
                        public void run() {
                            textView.setText("update");
                        }
                    });

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

(三)、使用sendMessage():

private Handler handler3 = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            textView.setText(msg.arg1 + "");
        }
    };

    private void method3() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    Message message = handler3.obtainMessage();
                    message.arg1 = 1;
                    handler3.sendMessage(message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

在这里,不建议直接new Message,Message内部保存了一个缓存的消息池,我们可以用obtain从缓存池获得一个消息,Message使用完后系统会调用recycle回收,如果自己new很多Message,每次使用完后系统放入缓存池,会占用很多内存的。

以下是对obtainMessage的源码解析:  

Message message = handler.obtainMessage();

    public final Message obtainMessage() {
        //此处的this就是Handler
        return Message.obtain(this);
    }

    Handler target;
    public static Message obtain(Handler h) {
        //创建一个Message,并将这个Message指定给一个target,这个target就是Handler自己,
        // 意思就是说把Message发送给Handler自己
        Message m = obtain();
        m.target = h;
        return m;
    }

    private static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;
    Message next;
    int flags;

    public static Message obtain() {
        //先尝试取出一个空的Message对象,如果没有就新建一个
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

(四)、使用sendMessage() 传递实体类:

@SuppressLint("HandlerLeak")
    private Handler handler4 = new Handler() {
        @SuppressLint("SetTextI18n")
        @Override
        public void handleMessage(Message msg) {
            textView.setText(msg.obj.toString());
        }
    };

    private void method4() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    Message message = handler3.obtainMessage();
                    message.obj = new Person(23, "zhang san");
                    handler4.sendMessage(message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    class Person {
        public int age;
        public String name;

        public Person(int age, String name) {
            this.age = age;
            this.name = name;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    '}';
        }
    }

三、源码解析:

我们知道在Handler调用之前是要进行Looper.prepare(),那么我们在实际使用过程中,往往没有写这个代码,是怎么回事呢,
原来, ActivityThread即主线程已经帮我们做这件事情了

public final class ActivityThread {
        public static void main(String[] args) {
            Looper.prepareMainLooper();
        }
    }


    public final class Looper {

        static final ThreadLocal sThreadLocal = new ThreadLocal();
        private static Looper sMainLooper;  // guarded by Looper.class

        final MessageQueue mQueue;
        final Thread mThread;

        public static void prepareMainLooper() {
            prepare(false);
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
                sMainLooper = myLooper();
            }
        }

        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));
        }

        private Looper(boolean quitAllowed) {
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }

        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }

    }

然后我们新建Handler,就可以直接使用了:

private Handler handler=new Handler();

    public class Handler {

        final android.os.Looper mLooper;
        final MessageQueue mQueue;

        public Handler() {
            this(null, false);
        }

        public Handler(android.os.Handler.Callback callback, boolean async) {

            mLooper = android.os.Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                        "Can't create handler inside thread that has not called Looper.prepare()");
            }
            mQueue = mLooper.mQueue;

        }

        public static @Nullable
        android.os.Looper myLooper() {
            return sThreadLocal.get();
        }

    }

比较关键的是这两个方法:

public final class Looper {
    
        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));
        }

    }

    public class Handler {

        public Handler(android.os.Handler.Callback callback, boolean async) {

            mLooper = android.os.Looper.myLooper();

        }
        public static @Nullable  android.os.Looper myLooper() {
            return sThreadLocal.get();
        }

    }

通过ThreadLocal 先set一个Looper,然后再get这个Looper。

你可能感兴趣的:(Android:Handler)