[原创]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

相关文章

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

JAVA保证HashMap线程安全的几种方式

《JAVA保证HashMap线程安全的几种方式》HashMap是线程不安全的,这意味着如果多个线程并发地访问和修改同一个HashMap实例,可能会导致数据不一致和其他线程安全问题,本文主要介绍了JAV... 目录1. 使用 Collections.synchronizedMap2. 使用 Concurren

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

jupyter代码块没有运行图标的解决方案

《jupyter代码块没有运行图标的解决方案》:本文主要介绍jupyter代码块没有运行图标的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录jupyter代码块没有运行图标的解决1.找到Jupyter notebook的系统配置文件2.这时候一般会搜索到