zoukankan      html  css  js  c++  java
  • handler looper和messageQueue

    一、用法。

    Looper为了应付新闻周期,在创建过程中初始化MessageQueue。

    Handler在一个消息到当前线程的其他线程

    MessageQueue用于存储所述消息

    Looper其中线程创建的对象。Handler的handleMessage方法就在哪个线程运行

    在创建activity时,android系统本身会为activity创建Looper。

    final Handler mainHandler = new Handler(getMainLooper())
    {
    	@Override
    	public void handleMessage(Message msg)
    	{
    		String content = "当前线程:" + "msg:" + msg.what;
    		Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
    	}
    };
    mainHandler.sendEmptyMessage(0x1);
    在其他线程中使用handler消息传递时,必须自己创建looper。以下的样例中HandlerThread封装了LooperMessageQueue,还实现了获取Looper的同步机制,比較好用。
    HandlerThread mThread = new HandlerThread("MyThread");
    mThread.start();
    Handler mHandle = new Handler(mThread.getLooper())
    {
    	@Override
    	public void handleMessage(Message msg)
    	{
    		String content = "当前线程:" + Thread.currentThread().getName() + "msg:" + msg.what;
    		System.out.println(content);
    	}
    };
    mHandle.sendEmptyMessage(0x2);

    二、Looper解析

    构造函数:

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
    }
    
    public static void prepare() {
        prepare(true);
    }
    
    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));
    }
    在prepare中创建了Looper实例。并在Looper的构造函数中创建了MessageQueue

    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
    
        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
    
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
    
            // This must be in a local variable, in case a UI event sets the logger
            msg.target.dispatchMessage(msg);
    
            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
    
            msg.recycle();
        }
    }
    

    在loop()中。Looper不断的通过queue.next()从MessageQueue取消息,然后调用语句msg.target.dispatchMessage(msg) 来运行。这里target为msg消息的发送者Handler,在分析Handler时再来分析。dispatchMessage在普通情况下会调用Handler类的handleMessage来处理消息。也就是上面样例中我们重载的这个handleMessage。

    三、Handler解析

    Handler的构造函数有非常多,这里选带Looper參数的构造函数

    public Handler(Looper looper) {
        this(looper, null, false);
    }
    
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
    

    再看sendMessage。

    public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

    sendEmptyMessage将message加到了Looper的MessageQueue中,之后Looper在loop()中调用queue.next()

    在enqueueMessage里面。我们看到了msg.target = this

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

    假设没有设置Callback的话,就会执行handleMessage了。

    四、HandlerThread解析

    HandlerThread继承于Thread,对Looper的操作进行了封装,做了同步处理。

    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
    
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }
    


  • 相关阅读:
    vue 表单 enter 键触发默认事件
    img找不到图片时,去除默认边框
    Javascript 计算
    Azure 上SQL Database(PaaS)Time Zone时区问题处理
    c#: 颜色选择控件之实现
    hive建库,建表,删表,删库,添加静或动态分区
    仿写一个 nodejs 中 queryString 的 parse 方法
    数独小游戏
    tnpm
    《翻页时钟特效》或者《日历翻页效果》的 css 部分原理实现
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4568949.html
Copyright © 2011-2022 走看看