[原创]Looper.parpare和Looper.loop()轻松玩转、子线程handler简单代码就可以理解。

本文主要是介绍[原创]Looper.parpare和Looper.loop()轻松玩转、子线程handler简单代码就可以理解。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前不久测试新版本内存泄露框架的时候,突然想虐一下自己,就写了个内存泄露的代码,并且还想让他泄露的时候不断弹出消息,但是不借助其他线程handler来实现,所以无聊写了个代码,发现验证是正确的,就把代码贴出来,给新手看看,也顺便把为什么可以这样做的原因发到这里。

问题列表

1、为什么主线程死循环而不卡死。
2、handler创建,子线程、使用

3、handler可以创建几个,Looper可以用几个。
4、handler的消息机制原理
5、子线程 弹出toast
6、looper.loop()阻塞了,那么之后的方法怎么才能实现调用, 那么让你在子线程搭建消息通讯你应该怎么搭建

回答

1、之所以不卡死,是因为它一直在处理消息,当没有消息的时候会进行等待,另外它也可以被其他线程唤醒。所以不会造成什么问题。
2、子线程先Looper.parpare() 实例化一个,一个线程只能有一个,
然后就可以创建了,发送的消息并不会被处理,需要开启looper.loop()
才能被处理。
3、handler可以创建多个,但是里面的looper一个线程只能拥有一个,looper只能创建一个,一般情况下不会把他给Loop.quit()的,因为无法再调用了。
4、原理就是hanlder发送的消息加入到消息队列,这个消息队列是threadlocal里面的,这个对象也是本身限制一个线程只能拥有一个,而Looper也是如此,加入的消息将会被Looper.looper()的死循环里面进行处理。
5、在handler.里面的run消息里面可以调用Loop.myLoopre().quit)来实现退出,这样就可以让looper()跳出阻塞。
主线程在应用启动的时候就开启looper了,是无法再prepare了,
子线程无法使用handler 是因为它是从自己线程取looper的,因此可以在子线程Looper.prepare一个,怎么搭建看下面的代码。

说明

网上很流行的文章就是子线程弹出toast的方法代码,但是没有下文,就是坑人的。

Loop.prepare()
Toast.makeText(activity.getApplication(),"" + Thread.currentThread()..getName()+ "线程的toast", Toast.LENGTH_SHORT).show();}
Loop.loop();

但是这样做了之后你怎么处理后面的逻辑?所以这是坑爹的,正确的方法是在loop()之前构建一个带线程延迟的死循环或者再开一个线程然后用这个线程的handler发送消息来实现处理。
下面的代码完美的演示了两种,让toast反复弹出来,而且这个代码是测试内存泄露的,你actiivty执行之后退出,它一直能反复弹出,直到弹出指定时间耗时才退出。

验证

下面代码演示的是

*** 模拟泄漏并且弹出toast* @param activity*/public static void testLeak(Activity activity) {if (!BuildConfig.DEBUG) {return;}Thread thread = new Thread(new Runnable() {@Overridepublic void run() {Activity activity1 = activity;Looper.prepare();Handler handler = new Handler();while (true) {try {Log.w(TAG, "继续持有对象" + activity+Thread.currentThread().getName());Thread.sleep(1000);handler.postDelayed(new Runnable() {int showCount = 0;@Override //反复发消息,这里就是永远死不掉的逻辑,public void run() {Toast.makeText(activity.getApplication(), activity.isDestroyed() + " isdestory? "+Thread.currentThread().getName(), Toast.LENGTH_SHORT).show();handler.postDelayed(this, 4000);//如果loop退出了,这里也不会再执行了if (showCount > 10) {Looper.myLooper().quit();//死掉吧。。}showCount++;}}, 2000);Looper looper = Looper.myLooper();new Thread("子子线程") {@Overridepublic void run() {String name = Thread.currentThread().getName();handler.post(new Runnable() {@Overridepublic void run() {//这类似在子线程中调用主线程的handler.post一样的道理,只不过这里是用的子线程的handler.来玩toast. 子线程本身已经looper.perpare了可以直接toast,但是现在和线程不行只能用叫做'子线程'的的handler进行使用Toast.makeText(activity.getApplication(),"我是再" + name + "线程的toast", Toast.LENGTH_SHORT).show();}});if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {Log.w(TAG, "loop quee count:" + looper.getThread().getName() + "" + ",是否当前线程:" + looper.isCurrentThread());}}}.start();Looper.loop();//这句话会阻塞了 主线程为什么死循环不会阻塞你就懂了,因为一直在handler里面循环,而且还有其他现成可以用主线程的handler给主线程发消息, 自身也一样可以。Log.w(TAG, "终于退出了");break;//loop已死,(阻塞)死循环下去没有意义了,looper.pare只能调用一次,除非反射清空死掉的looper// 。} catch (InterruptedException e) {e.printStackTrace();}}}});thread.setName("子线程");thread.start();}

这篇关于[原创]Looper.parpare和Looper.loop()轻松玩转、子线程handler简单代码就可以理解。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/959025

相关文章

Flutter监听当前页面可见与隐藏状态的代码详解

《Flutter监听当前页面可见与隐藏状态的代码详解》文章介绍了如何在Flutter中使用路由观察者来监听应用进入前台或后台状态以及页面的显示和隐藏,并通过代码示例讲解的非常详细,需要的朋友可以参考下... flutter 可以监听 app 进入前台还是后台状态,也可以监听当http://www.cppcn

Python使用PIL库将PNG图片转换为ICO图标的示例代码

《Python使用PIL库将PNG图片转换为ICO图标的示例代码》在软件开发和网站设计中,ICO图标是一种常用的图像格式,特别适用于应用程序图标、网页收藏夹图标等场景,本文将介绍如何使用Python的... 目录引言准备工作代码解析实践操作结果展示结语引言在软件开发和网站设计中,ICO图标是一种常用的图像

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

Java中有什么工具可以进行代码反编译详解

《Java中有什么工具可以进行代码反编译详解》:本文主要介绍Java中有什么工具可以进行代码反编译的相关资,料,包括JD-GUI、CFR、Procyon、Fernflower、Javap、Byte... 目录1.JD-GUI2.CFR3.Procyon Decompiler4.Fernflower5.Jav

Spring Boot 中正确地在异步线程中使用 HttpServletRequest的方法

《SpringBoot中正确地在异步线程中使用HttpServletRequest的方法》文章讨论了在SpringBoot中如何在异步线程中正确使用HttpServletRequest的问题,... 目录前言一、问题的来源:为什么异步线程中无法访问 HttpServletRequest?1. 请求上下文与线

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

javaScript在表单提交时获取表单数据的示例代码

《javaScript在表单提交时获取表单数据的示例代码》本文介绍了五种在JavaScript中获取表单数据的方法:使用FormData对象、手动提取表单数据、使用querySelector获取单个字... 方法 1:使用 FormData 对象FormData 是一个方便的内置对象,用于获取表单中的键值

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.