Android Hanlder机制分析(一) Hanlder常见用方法及原理

来源:互联网 发布:靠谱的代购淘宝店推荐 编辑:程序博客网 时间:2024/06/11 05:07

一、Handler介绍

  在android开发的过程中,经常需要对UI进行更新操作。但是在子线程中对UI进行更新在android中是不允许的,这涉及到了线程安全问题,因此更新UI只能在主线程(UI线程)中进行。但是如果将耗时操作放在了UI线程中会带来程序体验上卡顿甚至ANR等问题。然而通过Android的Handler机制能够很好解决此类问题。
  Handler为UI的异步跟新提供了一个很好的方式。Handler的主要作用是在子线程中进行耗时操作,将得到的数据通过handler 发送个主线程(UI线程)主线程根据结果进行UI的更新。

二、Handler相关方法介绍

  在使用Handler的时,通常需要将Handler消息发送给主线程,常用的方法如下:
  sendEmptyMessage(int what):发送空消息
   boolean sendEmptyMessageDelayed(int what,long delayMillis):指定多少毫秒之后发送空消息
  sendMessage(Message msg):立即发送消息
  sendMessageDelayed(Message msg,long delayMillis):指定多少毫秒之后发送消息
  obtainMessage():从消息队列中返回一个Message
  sendMessageAtFrontOfQueue(Message msg):将message插入到messageQueue前列。
方法还有很多,此处不一一列举。

三、Hanlder使用实例

  在使用Hanlder的时候通常需要以下几个步骤;

private Handler mHandler;
        mHandler = new Handler() {            @SuppressWarnings("unchecked")            public void handleMessage(Message msg) {                switch(msg.what) {                case XX:                需要执行的代码                    break;                case XX:                需要执行的代码                    break;                default:                    break;                }            }        };
 Message msg = new Message();  msg.what = XXX;mhandler.sendMessage();

总的说来分为了三步,先新建一个Handler的实例,再根据需求重写了handleMessage(Message msg)方法,最后通过mHandler发送消息交由handleMessage(Message msg)处理。

四 Handler实现原理

Handler的实现与三个组件相关:
1.Message:Handler接收和处理的消息对象
2.Looper:每个线程只能拥有一个Looper.它的loop方法负责读取MessageQueue中的消息,
读到信息之后就把消息交给发送该消息的Handler进行处理。
3.MessageQueue:消息队列,它采用先进先出的方式来管理Message.
  在一个activity中,程序自动的帮我们绑定了一个loop到主线程。在ActivityThread.java可以看到:

public static void main(String[] args) {        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");        SamplingProfilerIntegration.start();           ......        // Make sure TrustedCertificateStore looks in the right place for CA certificates        Looper.prepareMainLooper();        ActivityThread thread = new ActivityThread();        thread.attach(false);        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();                .......    }

因此,我们可以在UI线程中直接使用Handler。如果需要在自己线程中使用handler 则需要自己向线程绑定looper,具体实现在后面文章中详细解释。
现在我们来先看看 Looper,Message ,Handler他们之间的关系。
Message:消息的载体。可以携带消息种类、数据等信息。
(1)public int what:变量,用于定义此Message属于何种操作
(2)public Object obj:变量,用于定义此Message传递的信息数据,通过它传递信息
(3)public int arg1:变量,传递一些整型数据时使用
(4)public int arg2:变量,传递一些整型数据时使用
Looper:每一个线程只能有一个Looper,它负责这从MessageQueue中取出Message并将其分发给Handler处理。下面来看看Looper是怎么运行的。

public final class Looper {    private static final String TAG = "Looper";......    final MessageQueue mQueue;    final Thread mThread;    private Printer mLogging;    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));//    }    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;        ....../*循环里,不断从MessageQueue中取出msg ,根据msg所携带的信息进行分发*/        for (;;) {            Message msg = queue.next(); // 取出msg            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            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);//分发消息给handler 处理           ......    private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }

Handler 类主要用于处理自己发出的msg,而msg又在loop中进行取出。Handler源码如下:

 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());            }        }        mLooper = Looper.myLooper();//handler与looper绑定        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;//handler与msgqueue绑定        mCallback = callback;        mAsynchronous = async;    }

综上,在一个线程中绑定了一个looper后即成为了Looper线程。这looper线程中,可以新建Handler ,再通过handler实例向messageQueue中放入消息,放入的消息由looper取出再分发给相应的Handler处理。
(下一篇将写怎么去自建一个looperThread ,HanderThread ,以及hander.obtain()的优点)。

1 0