- 博客(70)
- 收藏
- 关注

原创 关于coroutine的异常捕获和取消机制
如果我们在launch外面try catch 意图捕获异常的话如果不是在抛出异常的地方直接捕获异常,那么在外面是捕获不到的,会直接导致应用奔溃。
2024-10-15 12:29:37
974

原创 flow 终极系列
collectLatest不会等待下游把事件处理完,而是继续发送,当下游收到新的事件后,会中止前面一个事件的处理,所以,我们只有看到,最后一个事件被处理完成,其他的都是知识开始,就中止了。普通的flow没有一个缓冲区,所以只能等前面的数据处理完之后,再发送下一个,但是如果我们给他加一个缓冲区buffer,这样,上游数据的发送不受下游处理速度的影响。会确保处理顺序,只有当前的流全部处理完毕后,才会继续处理下一个流,这点和。上游又发送了5,处理后变成6发送出去了,前一个的1变成3刚完成,发送了3。
2024-10-10 08:00:00
2788
原创 firebase异常捕获
data/user/0/com.xxxxx/files/.crashlytics. 下有文件。在代码中主动 throw RuntimeException(),但是控制台始终无法看到日志,配置 google-service.json。如何开启调试和查看日志呢?依赖,plugin等。
2025-06-12 15:33:57
93
原创 compose 保持屏幕常亮的工具类
利用view的 keepScreenOn属性,通过监听compose的resume和pause来给视图添加常亮。在需要常亮的地方通过。就可以添加界面常亮了。
2025-06-07 10:19:21
165
原创 apk图片资源优化,减小APK大小
png, svg转矢量图,webp到底用什么格式的图片呢?在Android开发中选择图片资源格式(PNG、SVG、WebP)需综合考虑。
2025-06-05 10:41:49
318
原创 内存泄漏修复示例
集成LeakCanary工具后,开发者可以检测并修复Android应用中的内存泄漏问题。LeakCanary通过弹窗提示内存泄漏,并生成详细的泄漏日志,帮助开发者定位问题。本文列举了1.0版本中检测并修复的多个内存泄漏示例,包括非静态内部类持有外部类引用、匿名内部类隐式持有Fragment引用、静态变量持有Fragment引用、服务广播未解绑、播放器SubtitleView未释放以及Handler未取消消息等。针对这些问题,提出了相应的修复方案,如将内部类改为静态类并使用弱引用、在Fragment销毁时断开
2025-05-22 11:50:41
593
原创 rememberLauncherForActivityResult使用示例
需求需要跳转到 CoursexxxActivity ,选择课程,选中课程后,会将课程对象放到返回的intent中。需要先定义ManagedActivityResultLauncher。那么如何启动这个Activity,并且获取返回的课程内容内。然后在需要启动跳转的时候。怎么启动intent呢。
2025-05-08 09:01:56
223
原创 AsyncImage 无法加载图片排查
排查到 原来的Activity 页面有如下代码。建议把这段代码移到 oncreate中,在非UI线程用的getresource。添加 onError = {修改之后,图片正常加载。
2025-05-06 09:21:23
222
原创 fragment 异常 InstantiationException
BadgeListInfoDialog有了有参数的构造函数,就没有了默认的无参构造函数。接手的项目过了下firebase和内存泄漏,还是有很多常见共性的问题。如果自定义了带参数的构造函数,系统无法找到无参构造方法,直接崩溃。这个异常也是非常常见,但是很多人不会去修复的。传递参数是 Android 的官方推荐做法。所以比如页面销毁重建的时候,就会报这个异常。在oncreate中。
2025-04-19 17:07:24
235
原创 关于viewpager常见的泄漏
但是这样比如在 mainfragment就就强引用了子fragment,这种强应用leakcanary不会报异常,但是Android studio的profile会报泄漏。在一个页面中 如果有用到tab,有需要进行fragment的切换,经常就看到了。这样就可以不直接引用fragment。
2025-04-19 16:29:40
245
原创 根据Exif信息纠正图片方向
throw IOException("无法解码图片: $originalPath")// 保存旋转后的图片,并重置 Exif 方向为正常。else -> 0f // 无需旋转。// 如果方向正常,直接返回原图路径。// 创建临时文件保存旋转后的图片。/ 工具函数:纠正图片方向并保存到新文件。// 读取原图的 Exif 方向。// 回收 Bitmap 内存。
2025-04-19 16:15:00
321
原创 上传文件worker
大文件在上传时如果全部加载进内存,容易造成 OOM(Out of Memory)。:网络中断时,如果是整个文件上传,一旦失败就要重头再来,耗时耗流量。:可以做断点续传、上传进度监控、更好地用户体验。如果文件很大,大到一个什么范围需要分段上传呢?:需要视设备内存情况和网络稳定性决定。:推荐强烈使用分段上传。:直接上传通常没问题。
2025-04-12 18:19:42
164
原创 通过uri获取文件路径手机适配
其实有的手机通过选择图片或者文件后返回的uri并不一定是媒体uri,也可能是document uri,造成这个时候直接通过 uri查询,找不到_data字段,需要将 document uri中分离出类型和id,在拼凑成新的uri,在通过contentprovider查询,才可以查出 _data字段中真正的路径。但是根据文档其实Android 10 之后是有新的字段,但是手机厂商众多,实现方式不一,还是找不到path怎么办,官方是说可以从 RELATIVE_PATH获取路径。
2025-04-12 17:39:01
530
原创 关于遗留项目重构反复看
如果一定要集成一个基类,比如实在不想每个fragment都添加方法,可以讲这个base写成具体的功能,不过Philip还是很拒绝使用继承来实现这些~~~~2. 关于一些可能的公共功能,将功能从viewmodel中抽离出来,并且用interface的方式来引用,通过依赖注入来初始化,便于测试。可能不太有必要,一些公用的方法可以通过ext扩展函数来实现。1. 关于 base fragment 的必要性?3.有些很好的flow的方式,可惜没有源码贴不出来。这个关于遗留项目的重构视频可以反复看。
2025-03-30 11:07:22
333
原创 关于application的persistent属性
从 Android 5.0(API 21)开始,Google 已不再允许普通应用使用 android:persistent="true",这个标志 仅适用于系统级应用(如 SystemUI、Telephony)。该属性用于指定 应用是否应该在系统启动时持久运行。如果设置为 true,Android 会尝试在设备启动时保留该应用,并尽可能不杀死它,即使系统内存紧张。作为系统应用,如果有persistent属性,则有可能无法重装,卸载等。之前的应用用了这个属性,且正好又是系统APP,
2025-03-29 14:15:10
245
原创 AlarmManager添加定时任务
通过AlarmManager添加定时任务,即使应用被杀死了,也会启动intent。用户静默安装前,定时自启动自身应用。直到应用启动完成,取消其他的定时任务。
2025-03-16 19:37:16
255
原创 Android studio取消代理
所以当取消代理的时候,只是将设置中的代理取消勾选,可视同步代码的时候,一直报org.apache.http.conn.HttpHostConnectException: Connect to 127.0.0.1:7890。Windows :C:\Users\Administrator.gradle下的gradle.properties中。Mac :/Users/.{用户目录}/.gradle下的gradle.properties中。以下为不同客户端下gradle.properties文件所在的目录。
2025-02-25 15:27:50
372
原创 旧项目内存泄漏修复
有个旧项目内存泄漏问题,用的是viewpager,页面多次跳转后,内存明显一直在增长,最后发现是viewpager中对fragment的引用导致。所以需要对adapter进行改造,不直接引用fragment,而是fragment的class。改造之后,页面跳转内存就平稳了。
2025-01-09 10:26:21
203
原创 采用koin 依赖注入进行viewmodel单元测试
桌面开发的viewmodel 和Android的viewmodel 创建方式不一样,Android有屏幕旋转,生命周期等感知。这样就可以通过注入的方式初始化viewmode。测试class要继承 KoinTest。在测试开始时,对koin进行初始化。
2024-11-12 19:04:11
635
原创 compose 桌面开发中如何使用KOIN依赖注入
在composable中使用viewmodel。在main.kt中初始化koin。写法和Android略有不同。其中module定义。
2024-11-11 17:55:28
318
原创 在多模块应用中使用navigation不知不觉都是这么用
核心common模块定义了Route1->screen1,Route2->screen2,Route3->screen3.....如果我现在单独使用 featureB,但是featureB中因为导航的这个逻辑,又要不得不去关联featureA。假设我们有主模块 app, 功能模块 featureA, featureB,所以,我们不该在内部的功能部分看到navigate的导航逻辑。所以,需要把导航的逻辑到需要通过lambda来提升到外部去。我们把导航逻辑写到模块中带来的问题是,
2024-11-01 09:12:19
179
原创 compose.material3 中的DatePicker在 desktop 平台同样可以适用
【代码】compose.material3 中的DatePicker在 desktop 平台同样可以适用。
2024-10-30 14:11:07
284
原创 compose navigation 自定义navtype
navController.navigate 直接放入带自定义参数的 route,在接收端,通过 toRoute直接获取组装后的带自定义参数的route,但是前提条件是,需要注册号typeMap。可以看到 DogDetailRoute带了两个参数,一个是自定义类型Dog。大部分情况下,我们应该是传狗的ID,然后在狗详情界面,通过查询本地数据库or API,去获取狗详情信息。通过自定义navtype可以方便的在导航过程中,传递自定义参数。即两个页面,一个狗列表页面,点击列表项,进入狗详情界面。
2024-10-19 22:14:18
344
原创 关于Android12以上的闪屏兼容
theme.xml</style></style>31多了动画定义<target其中 logo 定义图标,logo_animator定义动画了对logo中 animationgroup进行一些动画操作logo.xml<group</group></vector>应用主题这样当应用启动后,不需要添加额外的界面,就可以有一个logo的动画闪屏但是动画结束,如果我们想延长呢可以加setKeepOnScreenCondition) {!
2024-10-16 12:18:42
595
原创 微信消息语音播报秒实现
注册一个监听系统消息的服务实现这个服务,解析消息通知,如果是来自微信,则组装成微信消息,提取发送者,和消息内容,更新到livedata中怎么启动这个消息监听服务呢这时候会启动系统设置界面,我们需要允许我们的应用如何判断系统是否允许我们监听了呢允许了则直接跳过,不允许的话,启动设置界面,引导用户设置。
2024-10-16 11:04:30
880
原创 Room 引用复杂数据
在使用room的时候,如果要保存的entity中有 bitmap,或者其他复杂的对象,我们没办法直接保存,这个时候,就涉及到类型转换。比如下面这个entity,想要直接保存bitmap,这个时候,我们需要告诉room如何进行类型转换。写一个Converters,具体的转换方法上添加@TypeConverter注释。这样在保存数据的时候就可以直接操作了。然后将这个注册到数据库。读取也是可以直接返回。
2024-10-15 11:25:47
203
原创 关于Android的存储
关于数据的存储sp,datastore,内部存储,外部存储,数据库等对比,大概的一些概念关于内部存储和外部存储的一些区别,以及API29与API30平台上的区别PL这个视频大概有说到内部存储只有自己的应用可以访问,而且应用卸载后,可一起删除外部存储的的话,有个问题,就是应用卸载之后,文件还遗留着,然后Android就出了storage scope来解决这个问题,但是这个在Android 10之后引入的storagescope,但是在Andorid 11之后才强制;
2024-10-14 18:34:14
409
原创 datastore读取方式
看到在datastore上存储自定义的可序列化的对象之前项目中用到过datastore的preference,当时官网的介绍是这样的。
2024-10-14 18:06:43
392
原创 DataStore存储数据+加上加密
定义data class,添加 @Serializable 标签= null,= null这里先展示没有加密的的序列化存储的时候,将实例值转换成json string,再转换成bytearray写出到输出流,就可以保存到datastore的文件上了读取的时候,从输入流中读取转成json string, 再通过json解析成 UserSetting实例//继承datastore的Serializer,类型是我们定义的UserSettings//将输入端的内容先转换成string。
2024-10-13 18:50:13
1021
原创 Android上的AES加密
虽然这个视频讲的非常详细,但是涉及到具体底层算法,大致流程1. 将数据转成HEX或者byte array2.将数据分层一块块等大小的数据3.将数据和key 进行一次混合,加密之后的输出,在生成新的key4.将新的key和下一个数据,进行加密计算,继续重复生成的KEY长度有128,192,256,不同的的长度对算法的速度有影响当然key的长度越长,可能越安全这样具体的算法是什么呢。
2024-10-13 12:12:26
869
原创 调用AI 通过相机识别地标
我们希望可以通过ts模型识别图片,这个结果我们放在 Classification 中,自己定义。定义一个识别接口,然后我们可以有TS模型识别,以后有其他的模型,也可以实现其他的模型进行切换。并不是每一帧都是分析,所以加了 frameSkipCounter‘处理图片,根据ts 的文档,把图片裁剪处理成321*321。实现通过ts的API处理bitmap,识别,读取结果。我们在相机的Analyzer中使用分析器。如何在Android上使用ts模型。每60帧才分析,提高性能体验,这个模型大概就有50M了。
2024-10-11 12:37:02
1060
原创 CoroutineWorker 压缩图片示例
它允许开发者在后台执行任务,比如数据同步、图片上传、定期执行任务等,而不需要担心任务被中断,即使应用关闭或重启,任务仍会在条件满足时继续执行。根据图片,因为不知道图片多大,还一次次的压缩,直到达到压缩的指标大小了,将文件写入文件。可以设置任务的执行条件,比如仅在设备充电、联网等条件满足时执行。提供了更自然和可读的异步编程模型,避免了复杂的回调嵌套问题。会确保这些条件符合时,任务才会被执行。:通过使用 Kotlin 协程,:与普通的后台线程不同,怎么启动这个woker呢。
2024-10-10 20:08:09
417
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人