Hvac一次卡顿问题分析

通过查看anr/下的dumptrace日志,搜索空调包名,发现如下日志

复制代码
"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x731f9d08 self=0xb4000074f82f5380
  | sysTid=2790 nice=0 cgrp=foreground sched=0/0 handle=0x767ee3b4f8
  | state=R schedstat=( 43403965835908 128373803042 1427593 ) utm=4024919 stm=315476 core=1 HZ=100
  | stack=0x7fe0477000-0x7fe0479000 stackSize=8192KB
  | held mutexes=
  native: #00 pc 00000000000126ec  /system/lib64/libz.so (inflate_fast+412)
  native: #01 pc 0000000000010d00  /system/lib64/libz.so (inflate+4628)
  native: #02 pc 0000000000017b90  /system/lib64/libpng.so (png_process_IDAT_data+132)
  native: #03 pc 0000000000017968  /system/lib64/libpng.so (png_push_read_IDAT+480)
  native: #04 pc 0000000000016c60  /system/lib64/libpng.so (png_process_data+124)
  native: #05 pc 0000000000252fc8  /system/lib64/libhwui.so (SkPngCodec::processData()+344)
  native: #06 pc 0000000000254118  /system/lib64/libhwui.so (SkPngNormalDecoder::decodeAllRows(void*, unsigned long, int*)+96)
  native: #07 pc 000000000024acd4  /system/lib64/libhwui.so (SkCodec::getPixels(SkImageInfo const&, void*, unsigned long, SkCodec::Options const*)+336)
  native: #08 pc 0000000000254e04  /system/lib64/libhwui.so (SkSampledCodec::onGetAndroidPixels(SkImageInfo const&, void*, unsigned long, SkAndroidCodec::AndroidOptions const&)+540)
  native: #09 pc 0000000000246174  /system/lib64/libhwui.so (SkAndroidCodec::getAndroidPixels(SkImageInfo const&, void*, unsigned long, SkAndroidCodec::AndroidOptions const*)+744)
  native: #10 pc 00000000001b8508  /system/lib64/libhwui.so (doDecode(_JNIEnv*, std::__1::unique_ptr<SkStreamRewindable, std::__1::default_delete<SkStreamRewindable> >, _jobject*, _jobject*, long, long)+2856)
  native: #11 pc 00000000001b7828  /system/lib64/libhwui.so (nativeDecodeAsset(_JNIEnv*, _jobject*, long, _jobject*, _jobject*, long, long)+112)
  at android.graphics.BitmapFactory.nativeDecodeAsset(Native method)
  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:762)
  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:575)
  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:604)
  at com.desaysv.svhvac.view.widget.FrameAnimationView.a(SourceFile:174)
  at com.desaysv.svhvac.view.widget.FrameAnimationView.d(SourceFile:142)
  at com.desaysv.svhvac.view.widget.FrameAnimationView.a(SourceFile:27)
  at com.desaysv.svhvac.view.widget.FrameAnimationView$1.handleMessage(SourceFile:109)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:223)
  at android.app.ActivityThread.main(ActivityThread.java:7705)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1001)

这是主线程(main 线程)在做【同步 PNG 图片解码】,把 UI 线程堵死了 → 直接造成卡顿、掉帧、操作延迟!

为什么会卡?

图片解码是耗时、耗 CPU操作

绝对不能在主线程做!

但hvac代码的 FrameAnimationView 偏偏就在主线程解码帧动画 → 不卡才怪。

既然指出具体类,那么直接对此处理就好了

复制代码
 if (getVisibility() == VISIBLE) {
                // 异步解码 Bitmap,避免阻塞主线程
                final int currentIndex = mIndex;
                mLoadTask = mExecutor.submit(() -> {
                    Bitmap newBitmap = decodeBitmap(mDrawables[currentIndex]);
                    if (newBitmap != null) {
                        post(() -> {
                            // 在 UI 线程更新 Bitmap
                            if (mCurrentBitmap != null && !mCurrentBitmap.isRecycled()) {
                                mCurrentBitmap.recycle();
                            }
                            mCurrentBitmap = newBitmap;
                            invalidate();
                        });
                    }
                });
            }

非预加载模式下,将 decodeBitmap() 移到后台线程执行(使用已有的 mExecutor 线程池)

解码完成后通过 post() 回到 UI 线程更新 mCurrentBitmap 并调用 invalidate()

复用现有的 mLoadTask 来管理任务,可以在切换资源时取消未完成的加载

预加载模式不受影响,因为它已经是在后台线程加载的

这样修改后,主线程只负责调度和绘制,耗时的 Bitmap 解码在后台线程完成,不会再造成卡顿

相关推荐
JohnnyDeng949 小时前
【Android】Hilt 依赖注入:原理与最佳实践
android·kotlin·mvvm·hilt
星间都市山脉12 小时前
Android STS(Security Test Suite)完整介绍与测试流程
android·java·linux·windows·ubuntu·android studio·androidx
Yeyu12 小时前
你真的了解AIDL吗? 附:AIDL 与 Binder 交互全解析
android
dualven_in_csdn15 小时前
一键起飞调用示例
android·java·javascript
故渊at15 小时前
第十板块:Android 系统稳定性与调试 | 第二十五篇:Watchdog 与 ANR 的系统级监控
android·watchdog·系统稳定性·anr·超时监控
故渊at16 小时前
第十板块:Android 系统稳定性与调试 | 第二十六篇:Systrace 与 Perfetto 的系统级性能分析
android·perfetto·性能分析·systrace·系统稳定性
吕工-老船长199816 小时前
20260610----S905Y5(Android14)-----连接网络自动更新时间,时间设置为24小时
android
杉氧17 小时前
Kotlin 协程深度解析④:架构实战——在 MVVM/MVI 中的进阶应用
android·kotlin
Ab_stupid17 小时前
CTF-Android培训笔记
android·笔记