Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue

前言

最近刚好在做关于异步通信的需求,那么,今天我们来讲解下Android开发中的Handler异步通信传递机制(包括Looper、Message Queue)


目录

定义

Android提供的一套消息传递机制


作用

用于实现子线程对UI线程的更新,实现异步消息的处理:

- 在新启动的线程中发送消息

- 在主线程中获取并处理信息


为什么要用Handler

在安卓开发中:

- 为了保证Android的UI操作是线程安全的,Android规定了只允许UI线程修改Activity里的UI组件;

- 但在实际开发中,必然会用到多个线程并发操作UI组件,这又将导致UI操作的线程不安全

所以问题在于:如何同时满足:

- 保证线程安全

- 使多个线程并发操作UI组件

Handler消息传递机制就是解决这个问题的。


相关概念

主线程(UI线程)

- 定义:当程序第一次启动时,Android会同时启动一条主线程(Main Thread)

- 作用:主线程主要负责处理与UI相关的事件,所以主线程又叫UI线程

子线程则负责一些比较耗时的操作(联网、取数据、SD卡数据加载等操作),而主线程和子线程之间的通信,就是要靠Handler了。

Message

- 定义:消息,理解为线程间通讯的数据单元(Handler接受和处理的消息对象。)

例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程

Message Queue

- 定义:消息队列

- 作用:用来存放通过Handler发过来的消息,按照先进先出执行

Handler

- 定义:Handler是Message的主要处理者

- 作用:负责将Message添加到消息队列&处理Looper分派过来的Message

Looper

- 定义:循环器,扮演Message Queue和Handler之间桥梁的角色

  • 作用:主要负责消息循环:循环取出Message Queue的Message;消息派发:将取出的Message交付给相应的Handler

    1. 每个线程中只能拥有一个Looper,但是一个Looper可以和多个线程的Handler绑定起来,也就是说很多个线程可以往一个Looper所持有的MessageQueue中发送消息。这就给我们提供了线程之间通信的可能。
    2. Handler在创建的时候可以显示指定Looper,这样在Handler在调用sendMessage()投递消息的时候会将消息添加到指定的Looper里面的MessageQueue。如果不指定Looper,Handler默认绑定的是创建它的线程的Looper。

Handler异步通信机制工作流程图

![Handler异步通信传递机制流程图](http://img.blog.csdn.net/20160501142442982)


Handler、Looper、MessageQueue关系类图

![](http://img.blog.csdn.net/20160501142514338)

**Handler**
- 提供sendMessage方法,将消息放置到队列中
- 提供handleMessage方法,定义个各种消息的处理方式;

**Looper**
- Looper.prepare():实例化Looper对象;为当前线程生成一个消息队列;
- Looper.loop() :循环从消息队列中获取消息,交给Handler处理;此时线程处于无限循环中,不停的从MessageQueue中获取Message 消息 ;如果没有消息就阻塞

**MessageQueue**
- 提供enqueueMessage 方法,将消息根据时间放置到队列中;
- 提供next方法,从队列中获取消息,没有消息的时候阻塞;

**Handler工作流程解释**
异步通信传递机制步骤主要包括异步通信的准备、消息发送、消息循环和消息处理

  1. 异步通信的准备

    包括Looper对象的创建&实例化、MessageQueue队列的创建和Handler的实例化

  2. 消息发送

    Handler将消息发送到消息队列中

  3. 消息循环

    Looper执行Looper.loop()进入消息循环,在这个循环过程中,不断从该Message Queue取出消息,并将取出的消息派发给创建该消息的Handler

  4. 消息处理

    调用该Handler的dispatchMessage(msg)方法,即回调handleMessage(msg)处理消息

好像很复杂?那就先看下这个简图了解下:

![](http://img.blog.csdn.net/20160501142548296)


工作流程详细讲解

由上面可以得知,整个异步消息传递机制主要包括Handler、Looper和MessageQueue,接下来通过相应源码来解析这三部分

第一部分:Looper

Looper主要负责:
1. 自身的创建&创建Message Queue
2. 消息循环(消息取出、派发)

对应职责我们来看下相应的源码:
1. 自身的创建&创建Message Queue:prepare()方法

public static final void prepare() {
//判断sThreadLocal是否为null,否则抛出异常
//即Looper.prepare()方法不能被调用两次
//也就是说,一个线程中只能对应一个Looper实例
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
//sThreadLocal是一个ThreadLocal对象,用于在一个线程中存储变量
//实例化Looper对象并存放在ThreadLocal
//这说明Looper是存放在Thread线程里的
        sThreadLocal.set(new Looper(true));
}
//再来看下Looper的构造方法
private Looper(boolean quitAllowed) {
//创建了一个MessageQueue(消息队列)
//这说明,当创建一个Looper实例时,会自动创建一个与之配对的MessageQueue(消息队列)
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
}

**2. 消息循环:loop()方法**


public static void loop() {
//myLooper()方法作用是返回sThreadLocal存储的Looper实例,如果me为null,loop()则抛出异常
//也就是说loop方法的执行必须在prepare方法之后运行
//也就是说,消息循环必须要先在线程当中创建Looper实例
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread.");
        }
//获取looper实例中的mQueue(消息队列)
        final MessageQueue queue = me.mQueue;

        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
//进入消息循环
        for (;;) {
//next()方法用于取出消息队列里的消息
//如果取出的消息为空,则线程阻塞
            Message msg = queue.next(); // might block
            if (msg == null) {

                return;
            }

            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

//消息派发:把消息派发给msg的target属性,然后用dispatchMessage方法去处理
//Msg的target其实就是handler对象,下面会继续分析
            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
//释放消息占据的资源
            msg.recycle();
        }
}

总结Looper的作用:
1. 实例化本身、与当前线程绑定、创建与之相应的MessageQueue:prepare()方法

一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue

  1. 消息循环(消息取出、消息派发):loop()方法

    不断从MessageQueue中去取消息,派发给消息的target属性的Handler,然后调用相应Handler的dispatchMessage()方法进行消息处理。


第二部分:Handler

主要负责:
1. 在子线程发送消息给MessageQueue
2. 处理Looper派发过来的消息

使用Handler之前,会初始化一个Handler实例

Handler是需要和线程绑定在一起的,在初始化Handler的时候一般通过指定Looper对象从而绑定相应线程,即给Handler指定Looper对象=绑定到了Looper对象所在的线程中,Handler的消息处理回调会在那个线程中执行。一般有两种方法创建:

1. 通过Loop.myLooper()得到当前线程的Looper对象/通过Loop.getMainLooper()可以获得当前进程的主线程的Looper对象。

2. 不指定Looper对象,那么这个Handler绑定到了创建这个线程的线程上,消息处理回调也就在创建线程中执行.

首先看Handler的构造方法


public Handler() {
        this(null, false);
}
public Handler(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.myLooper()获取了当前线程保存的Looper实例,如果线程没有Looper实例那么会抛出异常
//这说明在一个没有创建Looper的线程中是无法创建一个Handler对象的
//所以说我们在子线程中创建一个Handler时首先需要创建Looper,并且开启消息循环才能够使用这个Handler。
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can‘t create handler inside thread that has not called Looper.prepare()");
        }
//获取了这个Looper实例中保存的MessageQueue(消息队列)
//这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了

        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

  • 上述说明:当Handler初始化时,可通过构造方法自动关联Looper和相应的MessageQueue

1. Handler向MessageQueue发送消息:对于Handler的发送方式可以分为post和send两种方式。

send的发送方法:sendMessage()

   public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 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
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
//调用了enqueueMessage方法
        return enqueueMessage(queue, msg, uptimeMillis);
    }

//调用sendMessage方法其实最后是调用了enqueueMessage方法
 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//为msg.target赋值为this,也就是把当前的handler作为msg的target属性
//如果大家还记得Looper的loop()方法会取出每个msg然后执行msg.target.dispatchMessage(msg)去处理消息,其实就是派发给相应的Handler
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
//最终调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去。
        return queue.enqueueMessage(msg, uptimeMillis);
    }

Post的发送方法:sendMessage()

  showhandler.post(new Runnable() {
                @Override
                public void run() {
                    String line = "\n";
                    StringBuffer text = new StringBuffer(show.getText());
                            text.append(line).append("angelababy:Yes,I do");
                            show.setText(text);
                }
  • 相比send方法,post方法最大的不同在于,更新UI操作可直接在重写的run方法定义。
  • 其实Runnable并没有创建什么线程,而是发送了一条消息,下面看源码:
 public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

  private static Message getPostMessage(Runnable r) {
//创建了一个Message对象
//创建Message对象可以new,也可以使用Message.obtain()方法;
//但是更建议使用obtain方法,因为Message内部维护了一个Message池用于Message的复用,避免使用new 重新分配内存。
        Message m = Message.obtain();
//将我们创建的Runable对象作为callback属性,赋值给了此message.
        m.callback = r;
//创建了一个Message对象
        return m;
    }

 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);
    }
  • 从上面的源码发现了吧?和send中的handler.sendMessage是一样的。

    调用了sendMessageAtTime,然后调用了enqueueMessage方法,给msg.target赋值为handler,最终Handler将消息加入MessagQueue.

  • 但是细心的你会发现,在使用Post方法时会将我们创建的Runable对象作为callback属性赋值给了此message

    那么msg的callback和target都有值,那么会执行哪个呢?

    我们已知回调发送消息的方法是:dispatchMessage()

 public void dispatchMessage(Message msg) {
//一开始就会进行判断
//如果msg.callback属性不为null,则执行callback回调,也就是我们的Runnable对象
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

####2. 处理Looper派发过来的消息:dispathMessage()方法


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

    public void handleMessage(Message msg) {
    }
  • 可以看到dispathMessage()方法里调用了 handleMessage()方法,但handleMessage()是一个空方法
  • 因为Handler发送消息过来是希望进行一定的处理,至于怎么处理消息是该Handler最终控制的,所以我们在创建handler时需要通过复写handleMessage()方法从而实现我们需要的消息处理方式,然后根据msg.what标识进行消息处理。

这就是为什么我们在主线程中实例化Handler的时候需要重写handleMessage()

特别注意

在一个Android应用启动的时候,会创建一个主线程,即ActivityThread(也叫UI线程),在ActivityThread中有一个静态的main方法:应用程序的入口点

//一个进程会默认生成一个主线程
public static void main(String[] args) {
 ......
//主线程生成时自动通过prepareMainLooper方法为主线程创建一个Looper
//prepare()方法是用于在子线程中创建一个Looper对象,在子线程中是可以退出消息循环的:调用消息队列的quit方法
//Looper生成时会自动生成与之配套的消息队列
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
 ......
//loop()方法开启消息循环
//主线程的消息循环是不允许被退出的
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

第三部分:MessageQueue

即消息队列,用于存放Handler发送过来的消息

为了提高插入删除的效率,采用单链表的方式实现。

对于MessageQueue,我们来看下入队和出队操作

MessageQueue入队

boolean enqueueMessage(Message msg, long when) {

    ......

    synchronized (this) {

        ......

        msg.markInUse();
        msg.when = when;
        Message p = mMessages;
        boolean needWake;
        if (p == null || when == 0 || when < p.when) {
            // New head, wake up the event queue if blocked.
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {
            // Inserted within the middle of the queue.  Usually we don‘t have to wake
            // up the event queue unless there is a barrier at the head of the queue
            // and the message is the earliest asynchronous message in the queue.
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            Message prev;
            for (;;) {
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                    needWake = false;
                }
            }
            msg.next = p; // invariant: p == prev.next
            prev.next = msg;
        }

        // We can assume mPtr != 0 because mQuitting is false.
        if (needWake) {
            nativeWake(mPtr);
        }
    }
    return true;
}

消息的入队(插入)过程

- 首先判断消息队列里有没有消息,没有的话则将当前插入的消息作为队头,并且这时消息队列如果处于等待状态的话则将其唤醒。

- 若是在中间插入,则根据Message创建的时间进行插入。

MessageQueue出队

Message next() {

    ......

    int nextPollTimeoutMillis = 0;
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }
// nativePollOnce方法在native层,若是nextPollTimeoutMillis为-1,这时候消息队列处于等待状态。   
        nativePollOnce(ptr, nextPollTimeoutMillis);

        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;

            if (msg != null && msg.target == null) {
                // Stalled by a barrier.  Find the next asynchronous message in the queue.
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
//按照我们设置的时间取出消息
            if (msg != null) {
                if (now < msg.when) {
                    // Next message is not ready.  Set a timeout to wake up when it is ready.
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // Got a message.
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    msg.markInUse();
                    return msg;
                }
            } else {
// 如果消息队列中没有消息,将nextPollTimeoutMillis设为-1,下次循环消息队列则处于等待状态
                nextPollTimeoutMillis = -1;
            }

//退出消息队列,返回null,这时候Looper中的消息循环也会终止。
            if (mQuitting) {
                dispose();
                return null;
            }

            ......
        }

        .....
    }
}

Thread、Looper、Handler之间的对应关系:

  • 一个Thread(线程)只能有一个Looper,可以有多个Handler
  • 一个Looper可以绑定多个Handler;
  • 一个Handler只能绑定一个Looper;


回顾工作原理图

把Handler工作原理都讲解完了,我们再来看下一开始说的工作原理图,你大概会有更深的理解了。


实例

没有实际应用的博客都不是好博客!现在是时候看一下实际应用了

1. 布局文件:

activity_main

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.carson_ho.handlerdemo.MainActivity">

    <TextView
        android:id="@+id/show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />
</RelativeLayout>

2. 1 send方法:MainActivity

package com.example.carson_ho.handlerdemo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private TextView show;
    private Handler showhandler;

    @Override
    //主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        show = (TextView) findViewById(R.id.show);
    //实例化Handler,这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue
        showhandler = new FHandler();
    //启动子线程
        new Thread_1().start();
        new Thread_2().start();

    }

    class FHandler extends Handler{
        //通过复写handlerMessage()从而决定如何进行更新UI操作
        @Override
        public void handleMessage(Message msg) {

            StringBuffer text = new StringBuffer();
            switch (msg.what) {
                case 1:
                    text.append("I love Carson_Ho");
                    show.setText(text);
                    break;
                case 2:
                    text.append("I hate Carson_Ho");
                    show.setText(text);
                    break;

            }
        }
    }

    class Thread_1 extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //定义要发送的消息
            Message msg = Message.obtain();
            msg.what = 1;//用于消息的标识
            msg.obj = "AA";//用于消息的存放
            //传入主线程的Handler并其MessageQueue发送消息
            showhandler.sendMessage(msg);
        }
    }

    class Thread_2 extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(8000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Message msg = Message.obtain();
            msg.what = 2;
            msg.obj = "BB";
            showhandler.sendMessage(msg);
        }
    }

}

2. 2 Post方法:MainActivity



package com.example.carson_ho.handlerdemo;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    public TextView show;
    public Handler showhandler;

    @Override
    //主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        show = (TextView) findViewById(R.id.AA);
        StringBuffer text = new StringBuffer();
        text.append("Carson_Ho:Do you love me?");
        show.setText(text);
    //实例化Handler,这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue
        showhandler = new Handler();
    //启动子线程
        new Thread_1().start();
        new Thread_2().start();

    }

    class Thread_1 extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            showhandler.post(new Runnable() {
                @Override
                public void run() {
                    String line = "\n";
                    StringBuffer text = new StringBuffer(show.getText());
                            text.append(line).append("angelababy:Yes,I do");
                            show.setText(text);
                }

                });
            }
        }

    class Thread_2 extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(8000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            showhandler.post(new Runnable() {
                @Override
                public void run() {
                    String line = "\n";
                    StringBuffer text = new StringBuffer(show.getText());
                    text.append(line).append("黄晓明:what the fuck?");
                    show.setText(text);
                }

            });
        }
    }
}


Demo的源码下载

https://github.com/Carson-Ho/Handler_learning


总结

本文对Handler异步通信机制全面解析(包含Looper、Message Queue)进行了全面介绍和分析,接下来我会介绍继续介绍Android开发中的相关知识,有兴趣可以继续关注Carson_Ho的博客!

请点赞!因为你们的鼓励是我写作的最大动力!

时间: 2024-10-26 13:00:20

Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue的相关文章

【Android自助餐】Handler消息机制完全解析(二)MessageQueue的队列管理

Android自助餐Handler消息机制完全解析(二)MessageQueue的队列管理 Android自助餐Handler消息机制完全解析二MessageQueue的队列管理 添加到消息队列enqueueMessage 从队列取出消息next 第一段 第三段 第二段 从队列移除消息removeMessages 第一个while 第二个while 关于这个队列先说明一点,该队列的实现既非Collection的子类,亦非Map的子类,而是Message本身.因为Message本身就是链表节点(见

【Android自助餐】Handler消息机制完全解析(一)Message中obtain()与recycle()的来龙去脉

[Android自助餐]Handler消息机制完全解析(一)Message中obtain()与recycle()的来龙去脉 Android自助餐Handler消息机制完全解析一Message中obtain与recycle的来龙去脉 提供obtain 回收recycle 提供obtain() 在obtain的所有重载方法中,第一行都是Message m = obtain();,即调用空参的方法. 先来看一下这个空参方法 public static Message obtain() { synchr

深入解析Android中Handler消息机制

Android提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange).Handler消息机制可以说是Android系统中最重要部分之一,所以,本篇博客我们就来深入解析Android中Handler消息机制. Handler的简单使用 为什么系统不允许子线程更新UI 因为的UI控件不是线程安全的. 如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那为什么不对UI控件的访

Android开发:AsyncTask源代码完全解析

从事Java开发以来,接触过很多的开源代码,自己能够明白代码但是想要表达出来却有点困难,从今天开始,逐渐开始对一些开源代码进行解析并记录成blog分享出来,希望以此提升自己的表达能力,如果文章中有什么出错之处,欢迎读者在评论中指出方便我及时的修正,以免误导其他读者,如果你有什么更好的建议也欢迎在下方留下你的评论,本人不胜荣幸.转载此文的朋友请带上原文的链接:http://blog.csdn.net/d_clock/article/details/43805779好,扯淡的话到此为止,接下来进入正

Android笔记二十五.Android事件Handler消息传递机制

因为Android平台不同意Activity新启动的线程訪问该Activity里的界面控件.这样就会导致新启动的线程无法动态改变界面控件的属性值.但在实际Android应用开发中,尤其是涉及动画的游戏开发中,须要让新启动的线程周期性地改变界面控件的属性值,这就须要借助Handler的消息传递机制实现. 一.Handler类简单介绍 1.功能 Handler类主要有两个作用 (1)在新启动的线程中发送消息; (2)在主线程中获取消息.处理消息.即当须要界面发生变化的时候.在子线程中调用Handle

Android之Handler源码深入解析

闲着没事,就来看看源码,看看源码的各种原理,会用只是简单的,知道为什么才是最牛逼的. Handler源码分析那,从使用的步骤来边用边分析: 1.创建一个Handler对象:new Handler(getMainLooper(),this); 这是我常用的一个方式,getMainLooper是获取主线程的Looper,this则是实现CallBack的接口 看一下Handler的构造函数 public Handler() { this(null, false); } public Handler(

android 开发Handler源码剖析

Android的消息机制主要是Handler的运行机制,而讲Handler的机制,又需要和MessageQueue和Looper结合.MessageQueue中文意思是消息队列,虽说叫队列,但是其内部结构并不是队列组成的,而是采用了单链表的形式来存储消息.MessageQueue只是负责存储消息,并不处理消息(这里指消息的轮训),Looper刚好弥补了这个空缺.我在知道,Handler创建的时候,会默认为我们创建一个Looper对象,那么如何获取当前的Looper呢,这里就使用到了一个Thead

Android Touch事件传递机制全面解析(从WMS到View树)

转眼间近一年没更新博客了,工作一忙起来.非常难有时间来写博客了,因为如今也在从事Android开发相关的工作,因此以后的博文也会很多其它地专注于这一块. 这篇文章准备从源代码层面为大家带来Touch事件的传递机制.我这里分析的源代码时Android4.4的. 说到分析源代码,光看肯定是不行的,一定要亲自去跟,而且要边跟边思考,所以在下一篇中.会有一个Demo来为大家详细分析源代码的走向. 以下进入正题,先来看下Android中事件的分类: 1.键盘事件:主要是指按下虚拟键盘的某个按键.或者机身的

Android开发之消息机制

转:http://stackvoid.com/introduction-to-Message-Handler-in-Android/ http://blog.dreamtobe.cn/2016/03/11/android_handler_looper/ Android应用程序主线程用来跟新UI,所以不能让主线程做费时操作,否则会出现ANR(App Not Response), 一般来说耗时操作都新开启一个线程,新线程执行结束,发消息给主线程来更新UI,常用方法有: Activity.runOnU