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 解码在后台线程完成,不会再造成卡顿

相关推荐
赏金术士8 小时前
Kotlin 习题集 · 高级篇
android·开发语言·kotlin
问心无愧051310 小时前
ctf show web 入门42
android·前端·android studio
没什么本事11 小时前
关于C# panel 添加lable问题 -- 明确X和Y 位置错误
android·java·c#
REDcker15 小时前
Android HWASan 详解:硬件标记原理、Clang 启用与排障实践
android·linux·debug·编译·clang·asan·hwasan
2501_9159090615 小时前
全面解析前端开发中常用的浏览器调试工具及其使用场景
android·ios·小程序·https·uni-app·iphone·webview
angerdream15 小时前
Android手把手编写儿童手机远程监控App之SQLite详解2
android
-SOLO-15 小时前
Python 爬取小红书 文章标题和内容 仅供学习
android·python·学习
ooseabiscuit16 小时前
Laravel5
android·php·laravel
科技道人17 小时前
Android 禁止使用ipv6 测试
android·禁用ipv6
AlexMaybeBot17 小时前
巧用 OpenClaw 为 Android 开发电脑瘦身
android·github·ai编程