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()的优点)。
- Android Hanlder机制分析(一) Hanlder常见用方法及原理
- android Hanlder原理分析
- Android Hanlder机制分析(二) HandThread Handler.Obtain()
- Android Hanlder-Message-Looper机制
- Hanlder消息传递机制及其工作原理
- hanlder机制(小白也能看的懂)
- Android Hanlder小例子
- Android Hanlder综合
- Android Hanlder处理
- Android消息处理机制、Hanlder机制(Handler、Looper、MessageQueue和Message)
- Android 开发-碎文 Hanlder
- Android hanlder message messagequeue Looper
- Android开发文档翻译(Hanlder Looper Message MessageQueue)
- Hanlder HttpURL...
- Hanlder作用
- Hanlder分析研究
- hanlder倒计时
- android hanlder loop message的理解
- web前端(001_滚动效果)
- HttpURLConnection类的保持session会话
- Android开发—RadioGroup中RadioButton默认选中问题
- [从头学绘画] 第37节 跆拳道二十四品势之8-花郞
- 复数类Complex
- Android Hanlder机制分析(一) Hanlder常见用方法及原理
- 网上java代码中文在subtext3中显示乱码
- Android白天/夜间模式Day/Night Mode标准原生SDK实现
- CSDN博客等级
- 自然语言处理会议
- MySQL 5.5 新增SIGNAL异常处理
- 如何让 beyond compare 只比较内容
- echarts图表(折线图、柱形图)
- SecureCRT issue "Could not open clipboard: Assess is denied" (无法打开粘贴板:访问被拒绝)