一个上线推广后才发现的大范围崩溃问题

先看问题

下面代码是一个简单的自定义View,很常用是吧,你们先看下这段代码有没有问题?

class TestView : FrameLayout {

    // 前面是一个堆构造方法,最后都会调用这个init()方法
    private fun init(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
    	// 主要是这里用了一个use方法,原意是想自动调用recycle方法释放内存的
        context.obtainStyledAttributes(attrs, R.styleable.TestView, defStyleAttr, 0).use {
        	// 一堆处理逻辑
        }
    }
}

代码就是这么个代码,这个代码有问题吗?

答案无非是三种:

  1. 代码100%没问题:那么问题就大了,我们的应用在上线前也是经过好几轮测试的,也都没有测出什么问题,即使线上80%的奔溃率后复测,也没复现。也不能怪测试,因为我们测试机确实有限,都是比较新的机器,这个问题在 Android11 以下才会有。
  2. 代码100%有问题:那么问题在哪里呢?但从上面的代码来看,也不一定有问题哦。
  3. 无法判断有没有问题:这就对了,因为后来我才发现,这个use方法就不止一个,还要看上面代码import了哪个use方法。

这个问题坑在哪里呢?

  1. 自定义View是一个非常常用的操作,这种写法也是很常用的,但是IDE不会报错,编译也不会报错。
  2. 这是在Android11以下才会报错,如果刚好你手上的测试机是Android12以上,那么你在开发阶段发现不了这个问题。
  3. 如果刚好测试们也没有用Android11以下的机子来测试,那么恭喜你,你会在上线后才发现这个问题。

问题分析

首先 context.obtainStyledAttributes(attrs, R.styleable.InputView2, defStyleAttr, 0) 会返回一个 TypedArray 对象,这个对象最后是要调用 recycle() 方法释放的。

然后我们懒惰用了kotlin提供的 use() 方法,让它自动释放,看看这个use长什么样:

public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        // 省略代码
    } finally {
    	// 省略代码
    	// 反正最后就是调用 close() 方法,也就是 Closeable 的 close() 方法
    	close()
    }
}

从上面代码可以看出最后是调用了 Closeable close() 方法,而 TypedArray 实现了这个接口:

public class TypedArray implements AutoCloseable {
    public void close() {
        recycle();
    }
}

一直到这里都是正常的,所以编译器也不会报错,测试也没有测出来。

那么问题来了,我去找了Android11的 TypedArray 的源码,并没有实现 Closeable 接口:

public class TypedArray {
	// 省略省略
}

解决方法

既然是 use() 引起的问题,那么不用它就是啦,直接用原始的 try catch 就行了。

但是,我发现 Jetpack 帮我们写了扩展方法:

public inline fun <R> TypedArray.use(block: (TypedArray) -> R): R {
    return block(this).also {
        recycle()
    }
}

所以,我们直接用就行啦,不过一定要记住 import 对了:

import androidx.core.content.res.use

class TestView : FrameLayout {

    private fun init(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
        context.obtainStyledAttributes(attrs, R.styleable.TestView, defStyleAttr, 0).use {
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/497144.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

13.Java能干什么?以及Java的三大平台

文章目录 一、JavaSE二、JavaME三、JavaEE JAVA从95年以来&#xff0c;已经问世了20多年了&#xff0c;可能比部分同学的年龄还大。 Java到底能干嘛呢&#xff0c;此时就需要讲到Java的三大平台&#xff0c;其实也就是它的三个分类&#xff1a;JavaSE、JavaME、JavaEE。 一、Ja…

【Web应用技术基础】CSS(5)——表格样式

第一题&#xff1a;表格边框 .html <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>HTML – 简单表格</title><link rel"stylesheet" href"step1/CSS/style.css"></head><bod…

Git 命令总览

Git Git 是一个版本控制系统&#xff0c;用于管理项目代码。通过 Git 可以轻松地进行代码的提交、更新和合并&#xff0c;确保项目代码的安全性和稳定性。同时&#xff0c;Git 还提供了丰富的工具和功能&#xff0c;如分支管理、代码审查、版本回退等&#xff0c;帮助开发更好…

docker容器内存检测排查

查询容器使用内存 在运维当中&#xff0c;你会发现内存很彪的高&#xff0c;但是如何判断为什么会高&#xff0c;是什么样的程序造成的呢&#xff1f;赶快使用 top&#xff0c;或者 free -h或者 ps -v。是吗&#xff1f;道理是对的。 但是你会发现&#xff0c;全部都是docker…

Java_19 罗马数字转整数

罗马数字转整数 罗马数字包含以下七种字符: I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1…

如何扫码登记信息?二维码登记信息更加简单快捷

现在很多场所会通过生成二维码的方式来做人员信息登记或者人员签到&#xff0c;那么这种扫描二维码填写信息的制作技巧是什么样的呢&#xff1f;想要做出这种效果&#xff0c;那么需要生成表单二维码&#xff0c;准备好问题和说明&#xff0c;通过专业工具的功能就可以轻松完成…

Redis中的LRU算法分析

LRU算法 概述 Redis作为缓存使用时&#xff0c;一些场景下要考虑内容的空间消耗问题。Redis会删除过期键以释放空间&#xff0c;过期键的删除策略 有两种: 1.惰性删除:每次从键空间中获取键时&#xff0c;都检查取得的键是否过期&#xff0c;如果过期的话&#xff0c;就删除…

轻松上手,小白也能免费部署自己的炫酷静态网站!(如何免费搭建个人网站)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 使用方法 📒📝 操作步骤📝 更换主题⚓️ 相关链接 ⚓️📖 介绍 📖 在互联网时代,拥有一个个人网站无疑是展示自我、分享知识或建立品牌形象的有效途径。然而,许多人在追求这一目标的过程中,常常因为成本、时间和技…

【C++】1320. 时钟旋转(1)

问题 类型&#xff1a;整数运算 题目描述&#xff1a; 时钟上面的时针从 m 时走到 n 时旋转了多少度&#xff1f;&#xff08;m≤n&#xff0c;且 m 和 n 都是1∼12之间的整数&#xff09;。 输入&#xff1a; 2 个整数 m 和 n。 输出&#xff1a; 1 个整数代表时针旋转的…

[数据结构]插入和希尔排序

一、插入排序 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴&#xff0c;但它的原理应该是最容易理解的了&#xff0c;因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法&#xff0c;它的工作原理是通过构建有序序列&#xff0c;对于未排…

全球金融市场的汇率与政策利率演变:历史与未来的交汇

根据国际货币基金组织&#xff08;IMF&#xff09;等平台的数据&#xff0c;整理了全球各国的兑美元汇率&#xff0c;短期利率、长期利率、政策利率数据&#xff0c;时间范围最新至2024年3月&#xff0c;希望对大家有所帮助 一、数据介绍 数据名称&#xff1a;全球各国汇率、短…

O2OA(翱途)开发平台-快速入门开发一个门户实例

O2OA(翱途)开发平台[下称O2OA开发平台或者O2OA]拥有门户页面定制与集成的能力&#xff0c;平台通过门户定制&#xff0c;可以根据企业的文化&#xff0c;业务需要设计符合企业需要的统一信息门户&#xff0c;系统首页等UI界面。本篇主要介绍通过门户管理系统如何快速的进行一个…

DoubleU-Net:一种用于医学图像分割的深度卷积神经网络

DoubleU-Net&#xff1a;一种用于医学图像分割的深度卷积神经网络 摘要引言相关工作方法 DoubleU-Net A Deep Convolutional Neural Network for Medical Image Segmentation–2020 摘要 语义图像分割是将图像中的每个像素标记为相应的类的过程。基于编码器-解码器的方法&…

如何在Win10使用IIS服务搭建WebDAV网站并实现无公网IP访问内网文件内容

文章目录 前言1. 安装IIS必要WebDav组件2. 客户端测试3. 使用cpolar内网穿透&#xff0c;将WebDav服务暴露在公网3.1 安装cpolar内网穿透3.2 配置WebDav公网访问地址 4. 映射本地盘符访问 前言 在Windows上如何搭建WebDav&#xff0c;并且结合cpolar的内网穿透工具实现在公网访…

银行监管报送系统介绍(十二):非居民金融账户涉税信息报送

国家税务总局、财政部、中国人民银行、中国银行业监督管理委员会、中国证券监督管理委员会、国家金融监督管理总局2017年5月9日发布、2017年7月1日起施行的《非居民金融账户涉税信息尽职调查管理办法》。 一、《管理办法》出台的背景是什么&#xff1f;   受二十国集团&…

软件设计师24--概念设计阶段

软件设计师24--概念设计阶段 考点1&#xff1a;概念设计过程考点2&#xff1a;E-R图属性E-R模型-联系类型判断例题&#xff1a;E-R模型-联系类型判断扩充的E-R模型 考点1&#xff1a;概念设计过程 需求分析 --> 抽象数据 --> 设计局部ER模型 --> 合并局部模型消除冲突…

接口自动化测试要做什么?8个步骤讲的明明白白

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 先了解下接口测试流程&#xff1a; 1、需求分析 2、Api文档分析与评审 3、测试计划编写 4、用例设…

2024年2月吸尘器行业线上电商(京东天猫淘宝)综合排行榜

鲸参谋监测的线上电商平台&#xff08;淘宝天猫京东&#xff09;2月吸尘器行业销售数据公开。 根据鲸参谋电商数据平台显示&#xff0c;吸尘器行业2月销量累计约53万件&#xff0c;环比上个月下滑29%&#xff0c;同比去年下滑19%&#xff1b;销售额累计约4亿&#xff0c;环比上…

原生js实现循环滚动效果

原生js实现如下图循环滚动效果 核心代码 <div class"scroll"><div class"blist" id"scrollContainer"><div class"bitem"></div>......<div class"bitem"></div></div> </di…

ES学习日记(一)-------单节点安装启动

基于ES7.4.1编写,其实一开始用的最新的8.1,但是问题太多了!!!!不稳定,降到7.4 下载好的安装包上传到服务器或虚拟机,创建ES目录,命令mkdir -p /路径xxxx 复制安装包到指定路径并解压: tar zxvf elasticsearch-8.1.0-linux-x86_64.tar.gz -C /usr/local/es/ 进入bin目录安装,命…
最新文章