
本文共 4549 字,大约阅读时间需要 15 分钟。
Handler机制:Android异步处理的核心
Handler的简单使用
Handler 是Android实现异步处理的核心工具,广泛用于在子线程中执行数据操作,并在操作完成后通过UI控件反馈结果。本文将深入分析Handler的工作原理及其在Android中的应用场景。
Step 1: 初始化Handler
Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.i("TAG", String.valueOf(msg.what)); }};
Step 2: 发送空消息
handler.sendEmptyMessage(1);
Step 3: 查看 日志输出
可以在Android Studio中查看以下日志:
I/TAG: 1
Handler的基础概念
Handler机制由Handler、Message、MessageQueue和Looper四部分组成。每个部分在Android系统中都有特定的职责:
Handler源码分析
理解Handler的内部逻辑工zung是掌握其工作原理的关键。
Step 1: new Handler()的源码解析
public Handler() { this(null, false);}
转化为:
public Handler(Callback callback, boolean async) { mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException("Can't create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
关键点:Looper.myLooper()
返回与当前线程关联的Looper实例。通常每个线程只能有一个Looper实例。
Step 2: sendEmptyMessage的实现
public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0);}
它内部调用:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { throw new RuntimeException("Looper has no message queue"); } enqueueMessage(queue, msg, uptimeMillis);}
最后调用:
private boolean enqueueMessage(MessageQueue queue, Message msg, long when) { msg.target = this; // Msg打包后存入Queue return queue.enqueueMessage(msg, when);}
关键点:无法直接使用子线程创建Handler,除非先调用Looper.prepare()
。
Looper的创建与循环
默认情况下,ActivityThread中的main
方法会自动初始化Looper:
public static void main(String[] args) { Looper.prepareMainLooper(); // 线程创建与attached操作... Looper.loop();}
关键点:
Looper.prepareMainLooper()
:为主线程创建Looper实例。Looper.loop()
:进入死循环,处理消息。
Step 3: Looper团辅阶段
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); }}// Internal methodprivate 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));}
关键点:每个线程只能有一个Looper实例。
Step 4: Looper的死循环
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; for (;;) { Message msg = queue.next(); if (msg == null) { return; } try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } msg.recycleUnchecked(); }}
关键点:由于是死循环,programmer must小心存入队的操作以避免资源耗尽。
Handler的注意事项
1. 子线程使用Handler需要注意的事项
在子线程中使用Handler需要执行以下步骤:
public class ExampleRunnable implements Runnable { @Override public void run() { Looper.prepare(); Handler handler = new Handler(); handler.sendEmptyMessage(1); Looper.loop(); }}
错误实例:
new Thread(new Runnable() { @Override public void run() { Handler handler = new Handler() { // handleMessage... }; handler.sendEmptyMessage(1); }}).start();
错误原因:未调用Looper.prepare()
,导致Handler无法获取到与线程关联的Looper。
2. handleMessage所在的线程
default情况下,msg.target(引用到Handler)的handleMessage方法会在Looper运行的线程被执行。这与ActivityThread有关。
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
handleCallback()
优先处理callback。handleMessage()
执行的是开发者定义的回调方法。
3. UI操作的限制
handleMessage
方法只能在主线程/UI线程中执行。在子线程中操作UI控件会导致crash。
4. Looper与Handler的关系
通过msg.target = this
,Message与当前线程的Handler关联。
总结
Handler机制是Android核心的异步处理工具,用于处理I/O密集型操作。通过Handler的简单使用,你可以轻松发送消息并在适当的位置处理事件。理解其内部机制有助于解决常见问题,如子线程使用Handler时的Looper准备问题。
理解了以上内容后,你可以更自信地在实际开发中使用Handler进行异步操作。如果有任何疑问,请通过实验和调试进一步加深理解。
发表评论
最新留言
关于作者
