handler分析
来源:互联网 发布:淘宝蛋糕店哪个好 编辑:程序博客网 时间:2024/06/14 06:03
面试时候经常被问到 handler是什么,说说你的理解...被问到这些心里就发毛,因为不知道从什么深度来说,说的深了,自己也没读过源码,细节的东西说不清反而不好,
我们可以看到handlerthread就是把looper给loop了,具体的干活的都是在looper里面了.不过从这个简单的类里面咱们可以复习一下java多线程的知识,看代码的注释..
messagequeue就不贴了,使用epoll的nio技术
看一下构造函数,如果我们在activity也就是主线程使用new handler(),那么这个handler的handlemessage函数就是运行在主线程,就是UI线程
就是把message往messagequeue里面enqueue一下.
说的浅了,这问题也没啥意义了..
从java层的代码来看看,handler和相关的一系列的类到底是怎么回事
先从handlerthread来看,handler也是作用在thread上的,看看handlerthread有啥不一样的
public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } /** * Constructs a HandlerThread. * @param name * @param priority The priority to run the thread at. The value supplied must be from * {@link android.os.Process} and not from java.lang.Thread. */ public HandlerThread(String name, int priority) { super(name); mPriority = priority; } /** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { } @Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); }//同下面的wait块,创建好了looper,notify一下wait的那边 Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ 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) { } } }//java里面典型的wait块,wait的时候会把thread moniter放弃,直到looper创建好了,执行notify. return mLooper; } }
我们可以看到handlerthread就是把looper给loop了,具体的干活的都是在looper里面了.不过从这个简单的类里面咱们可以复习一下java多线程的知识,看代码的注释..
看looper这个类
先要prepare,就是要创建looper的类,用到了threadlocal变量,因为是线程独有的.
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)); }loop的话 会调用messagequeue.next来得到下一个message,得到的话 会调用message包含的target,也就是handler的dispatchmessage函数.
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 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. 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.recycleUnchecked(); } }
messagequeue就不贴了,使用epoll的nio技术
看看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(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
看一下构造函数,如果我们在activity也就是主线程使用new handler(),那么这个handler的handlemessage函数就是运行在主线程,就是UI线程
而如果是在其他handlerthread的话,那么就是这个线程的looper.否则的话 就需要注明参数具体是哪个looper了
在看一下发送消息的函数
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); }
就是把message往messagequeue里面enqueue一下.
还有经常会问的问题就是handler和asynctask的区别.
aysnctask的默认的executor是串行执行的,也就是说会一个任务一个任务执行,如果一个app里面有N多图片要加载,而每个图片都是运行一个asynctask的话,那么就会非常的慢.
当然也可以使用并行的executor来.当然如果doinbackground之后有需要往UI线程写点东西,那么asynctask当然很方便了
可以看一下这个博客,图很清楚 http://www.cnblogs.com/anee/archive/2012/09/24/2699829.html
0 0
- Handler分析
- handler分析
- Handler分析
- Handler分析
- Handler分析
- Handler 源码分析
- Handler的源码分析
- Looper、Handler源码分析
- Android Handler 分析
- handler机制分析
- Handler,Looper分析
- Android Handler创建分析
- Handler源码分析
- [Android源码]Handler分析
- handler 源码分析
- Handler简介及分析
- Android Handler源码分析
- Handler机制分析
- solr增加相关总结
- MyBatis的动态SQL详解
- poj-2253 Frogger
- 基于MFC完整的OpenGL框架步骤
- ssh 登陆 amazon ec2 怎样不用密码
- handler分析
- C语言及程序设计初步例程-42 将数据输出到文本文件
- 基于MyBatis3.0.6的基本操作介绍
- CentOS安装基本库和开发环境
- Android学习笔记之详细讲解画圆角图片
- Amoeba实现mysql主从读写分离
- 工作流——顺序工作流和状态机工作流
- 路由器lan和wan的解释和网线插入
- 关于dp优化的问题