Leakcanary原理解析以及换肤框架skin的原理分析

2024年Android-skin-support 换肤原理全面解析(2),安卓面试题基础 文章所有资料全部已经打包整理好,另外小编手头上整理了大量Android架构师全套学习资料,Android核心高级技术PDF文档+全套高级学习资料+视频+2021 BAT 大厂面试真题解析资料展示:网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化学习资料的朋友,可以戳这里获取一个人可以走的很快,但一群人才能走的更远! 阅读详情
一、错误现场
 java.lang.ClassCastException: androidx.appcompat.widget.TintContextWrapper cannot be cast to android.app.Activity

 	at leakcanary.internal.navigation.ViewsKt.getActivity(Views.kt:16)

 	at leakcanary.internal.activity.screen.LeaksScreen.onGroupsRetrieved(LeaksScreen.kt:40)

 	at leakcanary.internal.activity.screen.LeaksScreen.access$onGroupsRetrieved(LeaksScreen.kt:23)

 	at leakcanary.internal.activity.screen.LeaksScreen$createView$$inlined$apply$lambda$1$1.invoke(LeaksScreen.kt:35)

 	at leakcanary.internal.activity.screen.LeaksScreen$createView$$inlined$apply$lambda$1$1.invoke(LeaksScreen.kt:23)

 	at leakcanary.internal.activity.db.Io$execute$2$1.invoke(Io.kt:52)

 	at leakcanary.internal.activity.db.Io$execute$2$1.run(Io.kt:12)

发生错误的代码:

// LeakCanary中Views.kt文件中的扩展属性
internal val View.activity
  get() = context as Activity

突如其来的Bug,让我措手不及。好好滴,leakcanary怎么会crash了?事出蹊跷必有妖啊,虽然crash发生在Leakcanary,
作为一个正义的程序猿,也不能把锅甩给Leakcanary。所以,为了分析这个问题,我趁机把leakcanary源码撸了一遍。原来发现是换肤框架利用

二、Leakcanary原理抽丝剥茧

作为一个Android程序猿,想必一定使用过Leakcanary这个三方库,他可以很方便的帮我们发现内存泄漏的问题。那么为了方便我们快速的抓住核心内容,我们从问题出发来剖析:

  • 问题一:Leakcanary如何检测和获取堆转储文件?

我们知道新版本的LC(为方便打字,以下用LC代替Leakcanary的拼写)是不需要初始化的,是通过ContentProvider来初始化的,当我们的应用启动的时候再Application的onCreate被调用之前,ContentProvider的onCreate会先调用,LeakCanary正好利用的这个机制,下面我们先看下LeakCanary监控内存泄漏以及如何获得堆转储文件:
在这里插入图片描述

上面的流程是LeakCanary的整个方法调用的细节,我们不需要记忆的,这里写出来只是供大家参考的,其中关键的几个步骤我用绿色的背景标识了。

第一个LeakCanary初始化的机制,这个上面介绍过;

第二个LeakCanary如何判断去评判一个页面等是否有内存泄漏,通过注册一个生命周期的回调,当页面调用到onDestroy时,也就是页面应该可以被销毁时,这个时机去做接下来的一些列判断;

第三个利用了当一个弱引用的对象编程弱可达对象,就会被放到队列里,这个时候我们通过将队列中的数据取出来,如果有值,说明对象已经是弱可达了,也就不会存在内存泄漏了,那我们就将其从被监测的对象列表中删除,否则就认为对象可能存在内存泄漏;

第四个关键的是通过调用GC,来强制GC一遍,但是我们知道**System.gc()**这个API是不能保证垃圾回收马上开始的,所以可以使用这个办法确保进行垃圾回收:

    override fun runGc() {
      // Code taken from AOSP FinalizationTest:
      // https://android.googlesource.com/platform/libcore/+/master/support/src/test/java/libcore/
      // java/lang/ref/FinalizationTester.java
      // System.gc() does not garbage collect every time. Runtime.gc() is
      // more likely to perform a gc.
      Runtime.getRuntime()
        .gc()
      enqueueReferences()
      System.runFinalization()
    }

    private fun enqueueReferences() {
      // Hack. We don't have a programmatic way to wait for the reference queue daemon to move
      // references to the appropriate queues.
      try {
        Thread.sleep(100)
      } catch (e: InterruptedException) {
        throw AssertionError()
      }
    }

第五个我们关心的是如何获取到堆信息并转储成文件呢(最关键的一行代码),那么我们可以使用Android系统的API如下:

Debug.dumpHprofData(heapDumpFile.absolutePath)

到这里拿到堆转储文件就是完成了我们的监控和收集的工作,接下来就是对文件的处理,以及怎样将处理后的信息通过页面清晰的展示出内存泄漏的原因。

早期的LeakCanary使用的是haha的库进行分析的,新版的LeakCanary使用的是shark库,进行分析的,那么这里就不再介绍shark是如何进行分析堆转储文件的。

三、换肤框架skin原理抽丝剥茧

换肤框架的一般思路是借助于Factory2来完成自定义inflate的。
为什么可以这么做?我们得先分析下当我们在Activity中通过setContentView()设置布局时,系统是如何创建对应的View的,下面是简化的时序图:
在这里插入图片描述

图中画的是系统会优先使用Factory2来创建View,但是默认情况下Factory2是空的,并没有实现。所以这个实现逻辑就提供给开发者一个可以自定义这个创建过程的逻辑,而换肤框架skin也是利用这一点来实现的。

在这里插入图片描述

skin换肤框架通过注入一个Factory2实例,从而改变系统默认的创建View的过程,再来看下skin框架实现Factory2接口的类:SkinCompatDelegate
在这里插入图片描述

所以使用换肤框架时,一些类型的View创建时传入的Context对象是使用TintContextWrapper包装后的实例,所以这时候View的getContext返回的对象是context的一个包装类实例,这个对象当然是不能强制转换成Activity的。所以才会出现文章开头出现的这个问题。

到这里,问题的根源就找到了,那如何解决呢,一种思路是,skin框架提供通过注解来声明哪些页面需要实现换肤的逻辑,默认是所有的Activity,所以我们只要在我们的基类里加注解(注解要稍微修改一下,改成可继承的),这个时候LeakCanary的页面就不会走换肤框架注入的逻辑,就能恢复正常了。

文章推荐:
史上最有趣的HTTPS漫画趣谈
通俗易懂的HashMap源码分析

我的又一个神奇的框架——Skins换肤框架 这个skinThemeColor拿到的就是当前皮肤下的真正的skin_theme_color颜色,比如R.color.skin_theme_color_orange的颜色值“#ff8400”或R.id.skin_theme_color_blue的颜色值“#0284e9”。当前skins框架只定义了几种主要的换肤属性,你理解原理后,也可以自己进行扩展,比如RadioButton的button属性等。我们只干预skin_开头的资源的加载过程,所以解析得到我们需要的属性,最后得到SkinAttr的列表返回。 阅读详情

相关推荐

skinsharp 函数文档

错误代码: SRET_OK 0 操作成功 SRET_ERROR 1 操作失败 SRET_ERROR_READ 2 皮肤文件读取失败 SRET_ERROR_PARAM 3 参数错误 SRET_ERROR_CREATE 4 创建皮肤失败 SRET_ERROR_FORMAT 5 皮肤格式错误 SRET_ERROR_VERSION 6 皮肤版本错误 SRET_ERROR_PA

程序道 -Learning, Thinking and Coding <存储知识的金库> 1516

使用SkinH实现MFC换肤 102种皮肤

说明 使用SkinH.dll和*.she后缀的皮肤库进行动态换肤。 效果 关键逻辑 void CSkinDemoDlg::OnCbnSelchangeComboSkinStyle() { int nIndex = m_combSkin.GetCurSel(); if (nIndex < 0) { return; } string strSkinName = m_vctFiles[nIndex]; std::stri...

jota 2424

MFC/WIN32程序美化之使用skinH更换皮肤

这样就可以使用皮肤了。

m0_60352504的博客 1634

Android-skin-support 换肤原理全面解析,2024年最新android实战开发教程

if (ap!if (!= null) {!} else {这里的这里,不得不说Android源码真是让在下佩服的五体投地,又一次体现了单一职责原则.你问我在哪里?系统将背景相关的交给AppCompatBackgroundHelper去处理,将文字相关的交给AppCompatTextHelper处理.

2401_84104883的博客 1511

skindemo: Android换肤框架实践指南

本文还有配套的精品资源,点击获取 简介:“skindemo”是一个旨在实现Android应用动态换肤功能的开源项目。通过在存储卡根目录放置特定应用,框架能够自动匹配并替换应用中的颜色和背景资源,无需手动设置每个UI元素。开发者通过学习该项目的资源匹配、动态加载机制和代码实现,可以轻松将个性化换肤功能集成到任何Android应用中,增强用户体验,同时也确保了加载过程的安全性和...

weixin_36431814的博客 1755

Skin插件化换肤实战技术

换肤

英雄联盟R3nzSkin换肤工具:5分钟实现安全免费的终极皮肤体验

R3nzSkin是一款专为英雄联盟玩家设计的开源内存换肤工具,通过创新的内存修改技术让你在不修改游戏文件的情况下安全体验所有皮肤。这款工具采用独特的内存级换肤机制,所有操作都在游戏运行时内存中完成,游戏结束后自动恢复原状,真正实现了"零痕迹"换肤体验,是英雄联盟玩家个性化游戏体验的终极解决方案。 ## 🎮 为什么选择R3nzSkin:三大核心优势 ### 1. 绝对安全的内存级操作 R3nz

gitblog_00131的博客 178

Python爬取京东商品数据保姆级教程(附源码及效果图)

本文介绍了一个基于Python的京东商品数据爬取教程,适合入门级开发者使用。文章详细讲解了从安装依赖库(DrissionPage、pandas等)到完成数据爬取的全过程,包括:1. 模拟用户搜索操作;2. 解析商品标题、价格、销量等关键信息;3. 处理复杂数据格式(如转换万级销量);4. 数据存储与Excel导出。教程提供了完整的封装函数,支持自定义搜索关键词和爬取数量,并包含错误处理和多种元素定位方式。最终数据会按时间戳命名导出为Excel文件,方便用于课程作业或毕业设计。

weixin_46449236的博客 1874

使用免费界面换肤软件 USkin

使用免费界面换肤软件 USkin作者:thirdwolf 下载源代码一、介绍   我们都知道,Skin以前是一项比较难的技术。但至从WindowsXP推出以来,Skin或者说Theme变得很普遍。虽然WindowsXP可以支持Theme,但当我们改变WindowsXP的风格时,所有支持WindowsXP风格的应用程序都变成一样的风格,如何让我们的软件不仅具备Skin,而且要靓丽更吸引人更有

大伟的代码空间 1414

ROS环境下UR机械臂与Realsense相机手眼标定实战指南

本文提供了在ROS环境下,对UR机械臂与Realsense相机进行手眼标定的完整实战指南。详细介绍了从环境搭建、软件包安装、硬件配置到分步数据采集与计算的完整流程,并分享了常见的避坑技巧与精度优化方法,旨在帮助开发者高效、准确地完成标定,为后续的机器人视觉应用奠定坚实基础。

sunny的博客 646

74HC138译码器的原理和使用

A0,A1,A2为3位二进制加权地址输入端口,A2A1A0顺序组成的3位2进制数对应的十进制数x控制使能端口Yx';例如当A2A1A0 = 101 时,其他门输出端全为高电平,只有Y5'为低电平。 Y0-Y7为8个输出端口,其输出电平由A0,A2,A3,E1,E2,E3决定。

diksan的博客 6万+

R3nzSkin国服免费换肤:五分钟试遍全联盟皮肤

R3nzSkin 是英雄联盟(LOL)国服的免费换肤工具。注入一次,对局中就能把任意皮肤切换出来做预览,效果只有你本地可见。从克隆到第一次换肤,跟着步骤走就能跑通。 ## 🚀 跑起来:从克隆到注入 这一节是一条时间线,按顺序做完你就有了一个能用的环境。 1. 克隆源码到你的本地目录(务必带上 `--recursive`): ```bash git clone --recursive ht

gitblog_01027的博客 185

COLMAP在Ubuntu下的编译陷阱与实战避坑指南——从环境配置到三维重建全流程

本文详细介绍了在Ubuntu系统下编译和配置COLMAP三维重建工具的全流程,包括环境准备、依赖库安装、CUDA加速配置以及常见编译问题的解决方案。通过实战案例演示了从图像特征提取到稠密重建的完整步骤,并提供了性能优化和问题排查的实用技巧,帮助用户高效完成三维重建任务。

weixin_29003437的博客 1048

英雄联盟换肤工具R3nzSkin全解析:基于内存级技术的安全使用指南

英雄联盟换肤工具R3nzSkin是一款采用内存级技术实现游戏皮肤切换的专业工具,通过动态内存注入技术在游戏运行时修改内存数据,实现不修改游戏文件的安全换肤方案。本文将从技术原理、安装流程、功能解析到安全规范,全面介绍该工具的使用方法与注意事项。 ## 一、内存换肤技术原理 R3nzSkin采用创新的动态内存注入技术,其核心原理是在游戏进程运行时对内存数据进行实时修改。与传统文件修改方式不同,该

gitblog_01015的博客 518

【可信数据空间-连接器技术架构设计方案】

一句话概括连接器是可信数据空间的“数据保镖”和“外交官”。连接器就是一个部署在你本地的软件代理,它代表你安全地对外提供数据服务,确保在共享数据价值的同时,牢牢守住数据的所有权和控制权。它是实现“数据可用不可见”这一理想的关键技术部件。一个生动的比喻:银行的金库和接待员想象一下,你的数据就是藏在银行金库里的黄金和钞票。金库(你的内部数据库): 绝对安全,外人绝对不能进。接待员(连接器): 坐在银行大厅里,负责与客户打交道。客户向接待员提出请求:“我想取1000元。

u014716614的博客 2264

39-高级优化技术:指令调度与乱序执行 - 手把手教你手写CPU

本文介绍了现代处理器设计中提高指令级并行性(ILP)的两种关键技术:指令调度和乱序执行。指令调度分为静态调度(由编译器完成)和动态调度(由硬件完成),后者能更好适应运行时情况但复杂度更高。乱序执行通过动态重排指令顺序提高硬件利用率,其核心组件包括重排序缓冲区、保留站和寄存器重命名。文章提供了保留站的Verilog实现示例,并分析了不同优化技术在性能、硬件开销和功耗方面的权衡。最终指出,CPU设计需根据性能、功耗等需求选择合适的优化技术。

2301_79143213的博客 85

R3nzSkin国服换肤工具:英雄联盟全皮肤免费解锁终极指南

还在为心仪的英雄皮肤而犹豫不决吗?R3nzSkin国服特供版专为中国服务器玩家量身打造,让你无需花费一分钱,就能体验英雄联盟所有皮肤的魅力。这款经过国服环境深度优化的免费换肤工具,提供安全稳定的换肤体验,彻底改变你的游戏视觉享受。 ## 🎯 为什么你需要R3nzSkin国服版? ### 传统换肤工具的痛点 - **兼容性问题**:国际版工具在国服经常失效 - **安全风险**:部分工具可能触

gitblog_00979的博客 409

树莓派 5 AI 套件(Hailo)示例

该用户自定义类作为输入传递给回调函数,该函数在管道输出上运行。它用于主程序与回调函数之间的通信。它对 hailo_rpi_common::app_callback_class 进行了扩展,并可根据应用程序的具体情况定制附加变量和方法。

机器人控制与仿真应用 4115

2024年Android最新Android-skin-support 换肤原理全面解析(3),2024年最新阿里巴巴二面到三面

本文讲解了我对Android开发现状的一些看法,也许有些人会觉得我的观点不对,但我认为没有绝对的对与错,一切交给时间去证明吧!愿与各位坚守的同胞们互相学习,共同进步!网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化学习资料的朋友,可以戳这里获取一个人可以走的很快,但一群人才能走的更远!

2301_82244125的博客 454

开源模型应用落地-qwen模型小试-入门篇(二)

在windows环境下,使用transformer设置模型参数/System Prompt/历史对话

以微薄之力,予他人些许温暖. 3232

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

[源码和文档分享]基于Skin++库实现的换肤功能

背景 之前自己经常使用MFC来开发一些界面程序,这些程序大都是自己练手用的。但,也会有极个别是帮别人开发,给别人使用。当你辛苦做出来的作品拿出去给别人用的时候,你总想让自己的作品给人留下深刻印象,无论是从功能,还是用程序界面上。 对于,我们使用 VC6.0 或者 VS2008、VS2010等以上版本开发出来的界面程序,界面通常都是千篇一律,非常...

qq_38474647的博客 237

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SkinSharp使用方法

  需要注意的是: 加载换肤后,程序关闭时,无需调用卸载皮肤接口,SkinSharp换肤库会自己完成清理工作。换肤时无需卸载皮肤,直接调用即可。   其DLL使用方法与前面几种皮肤库用法类似。如下: 1. 将动态库 SkinH.dll和皮肤文件SkinH.she拷贝到程序生成的目录;将 SkinH.h和皮肤文件 SkinH.lib拷贝到工程文件夹下。 2. 在预编译头文件 stdAfx...

xuq09的专栏 2319

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

VC皮肤库SkinSharp 1.0.6.6的使用

SkinSharp又称Skin#,是Windows环境下一款强大的换肤组件。 SkinSharp作为换肤控件,仅仅须要在您的程序中加入一行代码,就能让您的界面焕然一新,并拥有多种主题风格和色调的动态切换功能以及Vista透明边框特效。 站点地址:http://www.skinsharp.com/ 官方下载:http://www.skinsharp.com/htdocs/tar...

weixin_34024034的博客 157

给VC/SDK中的应用程序加上皮肤(实例演示)

<br />网上MFC加皮肤的资料蛮多的,SDK方面的相对较少,但是原理雷同,废话不多说了。<br />简单说明一下过程<br />1、复制 SkinH.dll、SkinH.lib、SkinH.h 以及皮肤文件MSN.she 至工程目录下;<br />  这里为了方便我直接把皮肤文件放到了一个文件夹中,在包含头文件的时候注意相应的路径就OK。<br />2、在工程中引入 .h 头文件及 Lib 静态库,大家在引用的时候要注意文件的路径;<br />#include "SkinH.h"<br />#pragm

yiruirui0507的专栏 3631

『原创』调戏 SkinSharp

最近想玩一下软件界面,百度了半天,发现 SkinSharp 挺强的。可是以前写的好多程序都懒得改源码了,所以想调戏一下 SkinSharp ,在没有源码的情况下,让任何一个 EXE 都可以使用 SkinSharp。本人是很尊重知识产权的,发这个贴子完全是出于技术交流的目的。如果你想使用 SkinSharp 请到官网 http://www.skinsharp.com/htdocs/index.htm

OSReact的专栏 1288
上一篇: 通俗易懂的HashMap源码分析
下一篇: Unable to select a master clock domain because no path can be found from “SYSTRACE“ to “LINUX_FTRACE
IT烂笔头
博客等级 码龄15年 621粉丝 78原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值