| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android面试必备知识点:Android中Handler八大问题汇总 -> 正文阅读 |
|
[移动开发]Android面试必备知识点:Android中Handler八大问题汇总 |
} sendMessage vs post 先来看看
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { msg.target = this; msg.workSourceUid = ThreadLocalWorkSource.getUid(); return queue.enqueueMessage(msg, uptimeMillis); }
post代码调用链: 调用 private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } 可以看到 for (;😉 { Message msg = queue.next(); // might block if (msg == null) { return; } msg.target.dispatchMessage(msg); }
也就是说`msg.target.dispatchMessa
ge public void dispatchMessage(@NonNull Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } // private static void handleCallback(Message message) { message.callback.run(); } 因为调用 总结? 3、Looper会一直消耗系统资源吗? 首先给出结论, 下面看下 消息出队 Message next() { // Return here if the message loop has already quit and been disposed. // This can happen if the application tries to restart a looper after quit // which is not supported. final long ptr = mPtr; if (ptr == 0) { return null; } int nextPollTimeoutMillis = 0; for (;😉 { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } nativePollOnce(ptr, nextPollTimeoutMillis); // While calling an idle handler, a new message could have been delivered // so go back and look again for a pending message without waiting. if(hasNoMessage) { nextPollTimeoutMillis =-1; } } } 上面的消息出队方法被简写了,主要看下面这段,没有消息的时候 if(hasNoMessage) { nextPollTimeoutMillis =-1; } 看for循环里面这个字段所其的作用: if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } nativePollOnce(ptr, nextPollTimeoutMillis);
/**
*/ 也就是说在用户线程要进入阻塞之前跟内核线程发送消息,防止用户线程长时间的持有某个对象。再看看下面这个方法: 当消息队列中没有消息的时候looper肯定是被消息入队唤醒的。 消息入队 boolean enqueueMessage(Message msg, long when) { if (msg.target == null) { throw new IllegalArgumentException(“Message must have a target.”); } if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle(); return false; } msg.markInUse(); msg.when = when; Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { // New head, wake up the event queue if blocked. msg.next = p; mMessages = msg; needWake = mBlocked; } else { // Inserted within the middle of the queue. Usually we don’t have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; for (;😉 { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } msg.next = p; // invariant: p == prev.next prev.next = msg; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; } 上面可以看到消息入队之后会有一个 if (needWake) { nativeWake(mPtr); } 方法,调用这个方法就可以唤醒线程了。另外消息入队的时候是根据消息的 4、android的Handle机制,Looper关系,主线程的Handler是怎么判断收到的消息是哪个Handler传来的?
5、Handler机制流程、Looper中延迟消息谁来唤醒Looper? 从3中知道在消息出队的 nativePollOnce(ptr, nextPollTimeoutMillis); 如果是延时消息,会在被阻塞 6、Handler是如何引起内存泄漏的?如何解决? 在子线程中,如果手动为其创建 Looper.myLooper().quit() 那么,如果在 具体可以参考 总结一下,解决 1 、有延时消息,要在 2、 匿名内部类导致的泄露改为匿名静态内部类,并且对上下文或者 7、handler机制中如何确保Looper的唯一性?
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)); } 可以看到,如果多次调用 8、Handler 是如何能够线程切换,发送Message的?
Thread thread=new Thread(new Runnable() { @Override public void run() { Looper.prepare(); |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 7:50:24- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |