android之handler机制深入解析

一、android中需要另开线程处理耗时、网络的任务,但是有必须要在UI线程中修改组件。这样做是为了:

  ①只能在UI线程中修改组件,避免了多线程造成组件显示混乱

  ②不使用加锁策略是为了提高性能,因为android中经常使用多线程。

handler就是为了解决在多个线程之间的通信问题。

二、基本使用:

  1 package com.dqxst.first.multithread;
  2
  3 import android.app.Activity;
  4 import android.os.Bundle;
  5 import android.os.Handler;
  6 import android.os.Handler.Callback;
  7 import android.os.Message;
  8 import android.util.Log;
  9 import android.view.View;
 10 import android.widget.TextView;
 11
 12 import com.dqxst.first.R;
 13
 14 public class HandlerActivity extends Activity {
 15     private TextView tv,msg_tv;
 16     private Handler handler = new Handler();
 17     final Handler msgHandler=new Handler(new Callback() {
 18         @Override
 19         public boolean handleMessage(Message msg) {
 20             //!!!在这里可以进行一些操作,返回true则将msg进行拦截
 21             return false;
 22         }
 23     }){
 24         @Override
 25         public void handleMessage(Message msg) {
 26             switch(msg.what){
 27             case 200:
 28                 msg_tv.setText("网络请求成功.");
 29                 break;
 30             case 404:
 31                 msg_tv.setText("not found!");
 32                 break;
 33             }
 34             super.handleMessage(msg);
 35         }
 36
 37     };
 38     private MyRunnable runnable = new MyRunnable();
 39
 40     @Override
 41     protected void onCreate(Bundle savedInstanceState) {
 42         super.onCreate(savedInstanceState);
 43         setContentView(R.layout.activity_handler);
 44         init();
 45
 46         Log.i("main", "主线程=" + Thread.currentThread().toString());
 47     }
 48
 49     class MyRunnable implements Runnable {
 50         @Override
 51         public void run() {
 52             int time = Integer.parseInt(tv.getText().toString());
 53             int now = time + 1;
 54             Log.i("main", "处理UI更新线程=" + Thread.currentThread().toString());
 55             tv.setText(now + "");
 56             //这里是将Runnable间隔1秒重新发送到消息队列中,所以是定时操作的效果
 57             handler.postDelayed(runnable, 1000);
 58         }
 59
 60     }
 61
 62     //下面主要是在子线程中调用post将消息加入到消息队列中
 63     public void startCallback(View view) {
 64         new Thread() {
 65             public void run() {
 66                 try {
 67                     Thread.sleep(1000);
 68                 } catch (InterruptedException e) {
 69                     e.printStackTrace();
 70                 }
 71
 72                 Log.i("main", "新线程=" + Thread.currentThread().toString());
 73
 74                 handler.post(runnable);
 75             }
 76         }.start();
 77     }
 78
 79     //这里是移除消息中的执行体部分,就是那个Runnable
 80     public void stopCallback(View view){
 81         handler.removeCallbacks(runnable);
 82     }
 83
 84     public void msgChange(View view){
 85         new Thread(new Runnable() {
 86             @Override
 87             public void run() {
 88                 Message message=Message.obtain();
 89                 if(Math.random()>0.3){
 90                     message.what=200;
 91                 }else{
 92                     message.what=404;
 93                 }
 94                 msgHandler.sendMessage(message);
 95             }
 96         }).start();
 97     }
 98
 99     private void init() {
100         tv = (TextView) findViewById(R.id.handler_tv);
101         tv.setText("0");
102         msg_tv=(TextView) findViewById(R.id.handler_tv_message);
103     }
104 }

handler基本使用

  由上例可以看到,handler使用有两种形式:

  ①post/postDelayed:这时传递的是一个Runnable对象,会封装到一个Message对象中发送到消息队列中

  ②sendMessage:这时需要重写handler的handleMessage或者在构造时传入一个实现Callback接口的对象(该对象的方法也是前面重写的方法名一样,但是先执行,可以用来对消息进行拦截)

三、源码分析:与handler机制有关的类有Looper、MessageQueue、Message以及Handler本身。

  1、Looper:主要有两个作用

    ①创建一个与当前线程相关的Looper实例,通过调用prepare()

 1    public static void prepare() {
 2         prepare(true);
 3     }
 4
 5     private static void prepare(boolean quitAllowed) {
 6         if (sThreadLocal.get() != null) {
 7             throw new RuntimeException("Only one Looper may be created per thread");
 8         }
 9         sThreadLocal.set(new Looper(quitAllowed));
10     }

prepare

    ②不断的读取MessageQueue中的消息,通过调用loop(),MessageQueue是和Looper相关的,由其创建和管理。注意:这个过程是阻塞的。

 1     public static void loop() {
 2         final Looper me = myLooper();
 3         if (me == null) {
 4             throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread.");
 5         }
 6         final MessageQueue queue = me.mQueue;
 7
 8         // Make sure the identity of this thread is that of the local process,
 9         // and keep track of what that identity token actually is.
10         Binder.clearCallingIdentity();
11         final long ident = Binder.clearCallingIdentity();
12
13         //这里是一个死循环,读取message
14         for (;;) {
15             Message msg = queue.next(); // might block
16             //!!!这里注意:通常不会执行这一句,除非使用quit退出Looper
17             if (msg == null) {
18                 // No message indicates that the message queue is quitting.
19                 return;
20             }
21
22             // This must be in a local variable, in case a UI event sets the logger
23             Printer logging = me.mLogging;
24             if (logging != null) {
25                 logging.println(">>>>> Dispatching to " + msg.target + " " +
26                         msg.callback + ": " + msg.what);
27             }
28
29             //这里是一个重点,说明了消息的具体执行方法
30             msg.target.dispatchMessage(msg);
31
32             if (logging != null) {
33                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
34             }
35
36             // Make sure that during the course of dispatching the
37             // identity of the thread wasn‘t corrupted.
38             final long newIdent = Binder.clearCallingIdentity();
39             if (ident != newIdent) {
40                 Log.wtf(TAG, "Thread identity changed from 0x"
41                         + Long.toHexString(ident) + " to 0x"
42                         + Long.toHexString(newIdent) + " while dispatching to "
43                         + msg.target.getClass().getName() + " "
44                         + msg.callback + " what=" + msg.what);
45             }
46
47             msg.recycleUnchecked();
48         }
49     }

loop

  2、Message:就是消息对象,一般使用都只是用来传递数据(从网络获取的)等,常用属性有

    ①what    :int类型,用于标识不同的消息,在handler中使用

    ②arg1,arg2  :int类型,用于传递int型的数据

    ③obj     :Object类型,用于传递对象

    ④data       :Bundle类型,

    创建Message有一些需要注意的点:

    ①使用Message.obtain()或者Handler.obtainMessage()进行创建而不是new,可以利用公共池中对象避免重新分配空间。

    ②一个Message是和一个handler关联的,表现为Message中的target属性,但是通常这个属性是由系统自动赋值的,就是那个发送该消Message到MessageQueue的handler。

  3、Handler:主要作用有以下三点

    ①关联所在线程的Looper对象和其所管理的MessageQueue对象,这是在构造函数中体现的,最终都会调用以下两个构造函数

 1     public Handler(Callback callback, boolean async) {
 2         if (FIND_POTENTIAL_LEAKS) {
 3             final Class<? extends Handler> klass = getClass();
 4             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
 5                     (klass.getModifiers() & Modifier.STATIC) == 0) {
 6                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
 7                     klass.getCanonicalName());
 8             }
 9         }
10
11         mLooper = Looper.myLooper();
12         if (mLooper == null) {
13             throw new RuntimeException(
14                 "Can‘t create handler inside thread that has not called Looper.prepare()");
15         }
16         mQueue = mLooper.mQueue;
17         mCallback = callback;
18         mAsynchronous = async;
19     }
20
21
22     public Handler(Looper looper, Callback callback, boolean async) {
23         mLooper = looper;
24         mQueue = looper.mQueue;
25         mCallback = callback;
26         mAsynchronous = async;
27     }

Handler构造函数

     !!!注意:在构造函数中,必须有一个Looper对象与其绑定,因为handler要将Message发送到MessageQueue中,而MessageQueue是由Looper创建的。

    ②发送消息到上面关联的消息队列,可以使用post和sendMessage两种类型方法。可以看到他们内部的调用过程是一样的。最终都是调用MessageQueue中的方法将消息绑定到一个链表上。  

 1     public final boolean post(Runnable r)
 2     {
 3        return  sendMessageDelayed(getPostMessage(r), 0);
 4     }
 5
 6     public final boolean postDelayed(Runnable r, long delayMillis)
 7     {
 8         return sendMessageDelayed(getPostMessage(r), delayMillis);
 9     }
10     //这是上面用到的将Runnable封装到Message中的方法
11     private static Message getPostMessage(Runnable r) {
12         Message m = Message.obtain();
13         m.callback = r;
14         return m;
15     }
16
17
18     public final boolean sendMessage(Message msg)
19     {
20         return sendMessageDelayed(msg, 0);
21     }

发送消息

 1     public final boolean sendMessageDelayed(Message msg, long delayMillis)
 2     {
 3         if (delayMillis < 0) {
 4             delayMillis = 0;
 5         }
 6         return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
 7     }
 8
 9
10     public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
11         MessageQueue queue = mQueue;
12         if (queue == null) {
13             RuntimeException e = new RuntimeException(
14                     this + " sendMessageAtTime() called with no mQueue");
15             Log.w("Looper", e.getMessage(), e);
16             return false;
17         }
18         return enqueueMessage(queue, msg, uptimeMillis);
19     }
20
21
22     private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
23         msg.target = this;
24         if (mAsynchronous) {
25             msg.setAsynchronous(true);
26         }
27         return queue.enqueueMessage(msg, uptimeMillis);
28     }

进一步的调用过程

    ③在Looper.loop()的循环读取过程中,读取的Message将通过msg.target.dispatchMessage(msg);交由Handler中的dispatchMessage()进行处理。

 1     public void dispatchMessage(Message msg) {
 2         if (msg.callback != null) {
 3             handleCallback(msg);
 4         } else {
 5             if (mCallback != null) {
 6                 if (mCallback.handleMessage(msg)) {
 7                     return;
 8                 }
 9             }
10             handleMessage(msg);
11         }
12     }

dispatchMessage

    这里就说明了Handler处理消息有三种方式。这里需要说明的是:

      a、msg.callback就是通过post/postDelayed或者构造函数传入的Runnable对象

      b、mCallback就是通过构造函数传入的实现其内部接口的对象,该方法返回true则退出,否则向下执行

四、扩展:

  0、HandlerThread:在上面的基本使用中,是创建一个子线程,然后在子线程中通过主线程中的handler实例向主线程的MessageQueue中发送消息。而该类的实现是将handler与子线程中的Looper/MessageQueue进行绑定,即利用该线程类的实现是将Handler发送和处理的Message存放在子线程中。该类的使用只需简单的两步即可

    ①实例化一个线程对象并开启该线程:HandlerThread downThread=new HandlerThread("ThreadName");downThread.start();

    ②将Handler与该线程的Looper绑定:Handler handler=new Handler(downThread.getLooper());

  1、在子线程中使用Handler(这里指的是在子线程中创建Handler实例来接受和Message)。通过上面的说明我们知道,Handler创建之前必须有一个该线程的Looper对象被创建。在主线程中直接使用是因为已经由系统进行创建了,此时在创建则会出错。下面是android中给出的标准使用方法:

 1 class LooperThread extends Thread {
 2         public Handler mHandler;
 3
 4         public void run() {
 5             Looper.prepare();
 6
 7             mHandler = new Handler() {
 8                 public void handleMessage(Message msg) {
 9                     // process incoming messages here
10                 }
11             };
12
13             Looper.loop();
14         }
15     }

LooperThread

  2、上面说主线程不能再创建Looper,这是因为主线程被初始化是就是一个Looper线程,各种消息都是通过Handler机制处理的。

  3、AsyncTask:异步消息处理机制,在内部封装了Handler处理流程。

    ①首先是android推荐的标准使用方式:创建一个子类,然后调用execute()即可

 1 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
 2      protected Long doInBackground(URL... urls) {
 3          int count = urls.length;
 4          long totalSize = 0;
 5          for (int i = 0; i < count; i++) {
 6              totalSize += Downloader.downloadFile(urls[i]);
 7              publishProgress((int) ((i / (float) count) * 100));
 8              // Escape early if cancel() is called
 9              if (isCancelled()) break;
10          }
11          return totalSize;
12      }
13
14      protected void onProgressUpdate(Integer... progress) {
15          setProgressPercent(progress[0]);
16      }
17
18      protected void onPostExecute(Long result) {
19          showDialog("Downloaded " + result + " bytes");
20      }
21  }

DownloadFilesTask

    这里简要说明三个泛型参数的作用:

      a、Params:就是后台执行需要的参数,例如下载时需要url

      b、Progress:就是任务执行的进度,在onProgressUpdate(Progress...)中会被使用,

       c、Result:就是任务完成返回的结果,在onPostExecute(Result)中进行处理。

       ②源码解析:首先说明,Handler机制就是在子线程中处理任务,通过Handler将需要处理的消息传递到与其绑定的Looper的消息队列中,再由Looper取出交由Handler处理。

      a、任务在子线程中处理,这里就是通过线程池处理,而任务就是doInBackground()中的部分,该函数被放在线程池的工作任务之中

 1    public AsyncTask() {
 2         mWorker = new WorkerRunnable<Params, Result>() {
 3             public Result call() throws Exception {
 4                 mTaskInvoked.set(true);
 5
 6                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 7                 //noinspection unchecked
 8 //!!!重点:doInBackground()在这里被封装
 9                 Result result = doInBackground(mParams);
10                 Binder.flushPendingCommands();
11                 return postResult(result);
12             }
13         };
14
15         mFuture = new FutureTask<Result>(mWorker) {
16             @Override
17             protected void done() {
18                 try {
19                     postResultIfNotInvoked(get());
20                 } catch (InterruptedException e) {
21                     android.util.Log.w(LOG_TAG, e);
22                 } catch (ExecutionException e) {
23                     throw new RuntimeException("An error occurred while executing doInBackground()",
24                             e.getCause());
25                 } catch (CancellationException e) {
26                     postResultIfNotInvoked(null);
27                 }
28             }
29         };
30     }

AsyncTask构造函数

        调用execute()就是用默认线程池来进行处理任务

 1     @MainThread
 2     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
 3         return executeOnExecutor(sDefaultExecutor, params);
 4     }
 5
 6
 7     public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
 8             Params... params) {
 9         if (mStatus != Status.PENDING) {
10             switch (mStatus) {
11                 case RUNNING:
12                     throw new IllegalStateException("Cannot execute task:"
13                             + " the task is already running.");
14                 case FINISHED:
15                     throw new IllegalStateException("Cannot execute task:"
16                             + " the task has already been executed "
17                             + "(a task can be executed only once)");
18             }
19         }
20
21         mStatus = Status.RUNNING;
22
23         onPreExecute();
24
25         mWorker.mParams = params;
26         exec.execute(mFuture);
27
28         return this;
29     }

线程池处理

        下面是这个线程池的本身部分,但是要注意:这是默认的情况,即调用execute()时的默认处理,默认处理是指:1、通过执行器模仿单一线程池的效果,即多个任务(一个AsyncTask实例的一次execute()创建一个任务)时只能有一个在线程中执行,2、而且线程中只能有128个任务(这是由阻塞队列的大小限制的)。

                   其实这是升级之后的效果,我们可以通过执行executeOnExecutor(Executor exec, Params... params)而不是execute()传入定制的线程池来解决上面问题。

 1 //这是一个执行器,负责添加任务到一个ArrayDeque队列中,并且将第一个任务分配给线程池处理。注意下面的execute是synchronized的,说明一次只能有一个线程在处理一个任务。
 2     private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
 3     public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
 4     private static class SerialExecutor implements Executor {
 5         final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
 6         Runnable mActive;
 7
 8         public synchronized void execute(final Runnable r) {
 9             mTasks.offer(new Runnable() {
10                 public void run() {
11                     try {
12                         r.run();
13                     } finally {
14                         scheduleNext();
15                     }
16                 }
17             });
18             if (mActive == null) {
19                 scheduleNext();
20             }
21         }
22
23         protected synchronized void scheduleNext() {
24             if ((mActive = mTasks.poll()) != null) {
25                 THREAD_POOL_EXECUTOR.execute(mActive);
26             }
27         }
28     }
29
30 //这是上面用到的线程池的设置
31     private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
32     private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
33     private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
34     private static final int KEEP_ALIVE = 1;
35
36     private static final ThreadFactory sThreadFactory = new ThreadFactory() {
37         private final AtomicInteger mCount = new AtomicInteger(1);
38
39         public Thread newThread(Runnable r) {
40             return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
41         }
42     };
43
44     private static final BlockingQueue<Runnable> sPoolWorkQueue =
45             new LinkedBlockingQueue<Runnable>(128);
46
47     public static final Executor THREAD_POOL_EXECUTOR
48             = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
49                     TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

执行器和线程池

        可以看到构造函数的任务对象中的最后一句是postResult(result),而该方法就是向AsyncTask内部的Handler发送消息。

       b、下面就到了Handler的部分,

 1     //获取内部Handler
 2     private static Handler getHandler() {
 3         synchronized (AsyncTask.class) {
 4             if (sHandler == null) {
 5                 sHandler = new InternalHandler();
 6             }
 7             return sHandler;
 8         }
 9     }
10
11     private static class InternalHandler extends Handler {
12         public InternalHandler() {
13             super(Looper.getMainLooper());
14         }
15
16         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
17         @Override
18         public void handleMessage(Message msg) {
19             AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
20             switch (msg.what) {
21                 case MESSAGE_POST_RESULT:
22                     // There is only one result
23                     result.mTask.finish(result.mData[0]);
24                     break;
25                 case MESSAGE_POST_PROGRESS:
26                     result.mTask.onProgressUpdate(result.mData);
27                     break;
28             }
29         }
30     }

AsyncTask内部Handler

        可以看到,这个handler处理两种类型的消息,一种是MESSAGE_POST_PROGRESS,由publishProgress发送,触发;一种是MESSAGE_POST_RESULT,由postResult发送。

 1 //发送MESSAGE_POST_PROGRESS消息,触发onProgressUpdate()
 2     protected final void publishProgress(Progress... values) {
 3         if (!isCancelled()) {
 4             getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
 5                     new AsyncTaskResult<Progress>(this, values)).sendToTarget();
 6         }
 7     }
 8     //所以重写这个方法可以在主UI中更新界面
 9     protected void onProgressUpdate(Progress... values) {
10     }
11
12
13     //发送MESSAGE_POST_RESULT消息,触发finish()
14     private Result postResult(Result result) {
15         @SuppressWarnings("unchecked")
16         Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
17                 new AsyncTaskResult<Result>(this, result));
18         message.sendToTarget();
19         return result;
20     }
21     //!!!这里的结束有两种情况,一种是被取消,一种是执行完成。
22     private void finish(Result result) {
23         if (isCancelled()) {
24             onCancelled(result);
25         } else {
26             onPostExecute(result);
27         }
28         mStatus = Status.FINISHED;
29     }

消息的发送和处理

  有关AsyncTask的使用还有一个问题就是如果在执行耗时任务时用户退出Activity,此时该任务线程可能没有执行完所以不会退出,这是可能造成内存泄露,需要在onPause中进行判断。还有其他问题参见http://droidyue.com/blog/2014/11/08/bad-smell-of-asynctask-in-android/index.html

参考:

http://threezj.com/2016/01/23/Android%20Handler%20Looper%20Message%20%20%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90/

http://blog.csdn.net/guolin_blog/article/details/11711405

时间: 2024-10-08 21:39:05

android之handler机制深入解析的相关文章

[学习总结]6、Android异步消息处理机制完全解析,带你从源码的角度彻底理解

开始进入正题,我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃.相信大家在日常的工作当中都会经常遇到这个问题,解决的方案应该也是早已烂熟于心,即创建一个Message对象,然后借助Handler发送出去,之后在Handler的handleMessage()方法中获得刚才发送的Message对象,然后在这里进行UI操作就不会再出现崩溃了. 这种处理方式被称为异步消息处理线程,虽然我相信大家都会用,可是你知道它背后的原理是什么样的吗?今天我们就来一起

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用Ima

Android的Handler机制

Handler机制的原理 Android 的 Handler 机制(也有人叫消息机制)目的是为了跨线程通信,也就是多线程通信.之所以需 要跨线程通信是因为在 Android 中主线程通常只负责 UI 的创建和修改,子线程负责网络访问和耗时操作, 因此,主线程和子线程需要经常配合使用才能完成整个 Android 功能. Handler 机制可以近似用图 1 展示.MainThread 代表主线程,newThread 代表子线程. MainThread 是 Android 系统创建并维护的,创建的时

[转]Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

Android事件分发机制 该篇文章出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识. 也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的 功能,ListView就不能滚动了?为什么图片轮播器里的图

(转) Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用Ima

【转】Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9153761 记得在前面的文章中,我带大家一起从源码的角度分析了Android中View的事件分发机制,相信阅读过的朋友对View的事件分发已经有比较深刻的理解了. 还未阅读过的朋友,请先参考 Android事件分发机制完全解析,带你从源码的角度彻底理解(上) . 那么今天我们将继续上次未完成的话题,从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是View

【转载】Android 的 Handler 机制实现原理分析

handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段.使用起来很简单,就两个步骤,在主线程重写handler的handleMessage( )方法,在工作线程发送消息.但是,有没有人想过这种技术是怎么实现的呢?下面我们一起探讨下. 先上图,让大家好理解下handler机制: handler机制示例图 上面一共出现了几种类,ActivityThread,Handler,MessageQueue,Looper,msg(Message),对这些类作简要介绍: ActivityThr

Android异步消息处理机制完全解析,带你从源码的角度彻底理解

转载于:http://blog.csdn.net/guolin_blog/article/details/9991569 之前也是由于周末通宵看TI3比赛,一直没找到时间写博客,导致已经有好久没更新了.惭愧!后面还会恢复进度,尽量保证每周都写吧.这里也是先恭喜一下来自瑞典的Alliance战队夺得了TI3的冠军,希望明年中国战队能够虎起! 开始进入正题,我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃.相信大家在日常的工作当中都会经常遇到这个问题

Android之Handler源代码深入解析

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