当前位置: 首页 > news >正文

优化android14低内存设备连接蓝牙键盘/鼠标后点击Disconnect断开蓝牙连接,页面卡顿(将1180ms优化到629ms)

目录

1.背景

2.分析

3.解决方案


1.背景

在ST进行测试的过程中,发现在连接蓝牙键盘和鼠标并在设备详情界面断开连接的时候页面有卡顿现象,这里不方便展示,就是在蓝牙的设备详情界面,然后点击断开会有卡顿现象

如下是详细的描述:

在 Android 系统的蓝牙设备详情页(Settings App)中,当我们点击“断开连接(Disconnect)”按钮来断开一个**蓝牙鼠标**时,出现了严重的视觉卡顿:
1. 手指按下按钮,Material Design 的灰色水波纹(Ripple)刚荡漾出来一半,整个画面瞬间**冻结**。
2. 画面卡死约 1 秒钟。
3. 1 秒后,画面恢复,按钮文字突变为“Connect(连接)”。

本文就介绍如何优化这个问题,将蓝牙断开的流程从1180ms优化到629ms,并且解决水波纹卡住问题

2.分析

其实发现在内存低的设备上整体都是比较卡卡的状态,所以有一些稍微更加卡顿的界面就会凸显出来,其实代码都是google的android 14源码,主要就是设备的区别,然后我们来分析下这种问题怎么处理

首先查看日志

日志耗时分析:

开始断开:04-09 20:14:21.610

更新已断开状态:04-09 20:14:21.976

界面刷新:04-09 20:14:22.790

上述进行总结:

点击断开到上层收到状态已断开耗时:366ms

点击断开到界面显示已断开耗时:1180ms

然后我们查询日志中的异常点,如下是在一次断开的流程中相关的异常日志

可以看出来在断开蓝牙的过程中居然界面重新启动了,这肯定是会耗时很多的,然后我们在看看有没有其他异常信息

可以看出来在测试的过程中甚至有掉帧现象,所以肯定是界面显示卡顿的,主线程有时卡顿1秒钟,这肯定肉眼看起来很卡顿

上述我们得到两个信息,

1是鼠标和键盘在断开蓝牙过程中重新启动了Activity

2是由于设备配置太低,主线程已经处理不过来突如其来的大量刷新任务,其实在加日志查看的过程中由于Settings/SystemUI设计的臃肿性导致断开蓝牙后有15个组件一起刷新,所以导致主线程根本处理不过来

3.解决方案

首要解决的就是在断开蓝牙过程中Activity重启现象,在AndroidManifest中对应的Activity添加如下标识符,让其在蓝牙断开连接过程中不会重新启动Activity

android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation"

这样我们的耗时过长问题基本解决了,但是发现还是会卡顿,水波纹显示不出来,其实从日志中这时我们从日志中查看onCreate的打印没有了,但是还是会打印出来

Skipped 48 frames! The application may be doing too much work on its main thread.

其实上述虽然我们让其不重新启动了,但是臃肿(15个组件一起更新)的问题还是存在的,所以此时我们需要排优先级,先把点击断开过程的水波纹显示出来,然后开始进行断开流程

这里我们用view.postDelay方式即可

此时优化的差不多了,然后我想进一步优化,就把一些可以放在子线程的方法给放到子线程中了,如下是最终的patch

diff --git a/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 803ad1c..848c989 100644 --- a/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -50,6 +50,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; +import com.android.settingslib.utils.ThreadUtils; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -399,17 +400,19 @@ } public void onReceive(Context context, Intent intent, BluetoothDevice device) { - if (device == null) { - Log.w(TAG, "StateChangedHandler receives state-change for invalid device"); - return; - } + ThreadUtils.postOnBackgroundThread(() -> { + if (device == null) { + Log.w(TAG, "StateChangedHandler receives state-change for invalid device"); + return; + } - CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); - if (cachedDevice == null) { - Log.w(TAG, "StateChangedHandler found new device: " + device); - cachedDevice = mDeviceManager.addDevice(device); - } - onReceiveInternal(intent, cachedDevice); + CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); + if (cachedDevice == null) { + Log.w(TAG, "StateChangedHandler found new device: " + device); + cachedDevice = mDeviceManager.addDevice(device); + } + onReceiveInternal(intent, cachedDevice); + }); } protected void onReceiveInternal(Intent intent, CachedBluetoothDevice cachedDevice) { diff --git a/qssi14/packages/apps/Settings/AndroidManifest.xml b/qssi14/packages/apps/Settings/AndroidManifest.xml index bc116f1..2492c81 100644 --- a/qssi14/packages/apps/Settings/AndroidManifest.xml +++ b/qssi14/packages/apps/Settings/AndroidManifest.xml @@ -247,7 +247,8 @@ android:exported="false" android:theme="@style/Theme.SubSettings" android:knownActivityEmbeddingCerts="@array/config_known_host_certs" - android:taskAffinity="com.android.settings.root" /> + android:taskAffinity="com.android.settings.root" + android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation" /> <activity android:name=".Settings$CreateShortcutActivity" android:exported="true" @@ -4533,6 +4534,7 @@ <activity android:name="Settings$BluetoothDeviceDetailActivity" android:label="@string/device_details_title" android:exported="true" + android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation" android:permission="android.permission.BLUETOOTH_CONNECT"> <intent-filter android:priority="1"> <action android:name="com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS" /> diff --git a/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java b/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java index 2ade4ec..c48c8ee 100644 --- a/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java +++ b/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java @@ -25,6 +25,7 @@ import com.android.settings.R; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.widget.ActionButtonsPreference; /** @@ -72,9 +73,14 @@ .setButton2Text(R.string.bluetooth_device_context_disconnect) .setButton2Icon(R.drawable.ic_settings_close) .setButton2OnClickListener(view -> { - mMetricsFeatureProvider.action(mContext, - SettingsEnums.ACTION_SETTINGS_BLUETOOTH_DISCONNECT); - mCachedDevice.disconnect(); + view.postDelayed(() -> { + view.jumpDrawablesToCurrentState(); + mActionButtons.setButton2Enabled(false); + ThreadUtils.postOnBackgroundThread(() -> { + mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_SETTINGS_BLUETOOTH_DISCONNECT); + mCachedDevice.disconnect(); + }); + }, 150); }); mConnectButtonInitialized = true; }
http://www.jsqmd.com/news/856352/

相关文章:

  • 主流软件开发框架对比
  • 2026 年上海电商财税公司排名 TOP8 商家选择避坑指南
  • MH Markets迈汇的本地团队反应是否积极?地区化支持完不完善?
  • 2026杭州主城区沿江千万级豪宅盘点:在售稀缺精装大平层带泳池品质新盘推荐 - 匠言榜单
  • 一文看懂区块链:从“多人记账本”到数字世界的信任机器
  • Perplexity历史资料搜索精准度跃升关键:基于时间感知RAG的4层重排序模型(含可复现Python验证脚本)
  • 2025-2026年拆迁律所电话推荐:专业法律咨询指引 - 品牌推荐
  • 口碑好的中天光合叶绿素哪家好
  • 云服务器怎么选、怎么省、怎么稳
  • 高中学习机选购指南:告别营销陷阱,用科学逻辑选对真正有用的产品
  • 2025-2026年国内pof膜品牌推荐:五款排行产品专业评测解决仓储运输致收缩不均痛点 - 品牌推荐
  • 【Coze工作流】调试排错实战:7个高频报错从踩坑到跑通
  • 2025-2026年北京老房改造装修公司推荐:五家排名产品评测夜读防噪音的案例 - 品牌推荐
  • 比完美主义更害人的,是“先做个垃圾出来”
  • 如何选亚克力板加工厂?2026年5月推荐五家户外广告牌不褪色产品评测对比 - 品牌推荐
  • LizzieYzy:从围棋爱好者到AI分析高手的进阶之路
  • linux内存惰性分配:从虚拟地址到物理页的深度解析
  • 2025-2026年全球包装线品牌推荐:五大排行厂商专业评测解决饮料产线致漏液痛点 - 品牌推荐
  • Perplexity翻译查询功能调优手册:从响应延迟>2.4s到<380ms的6步性能攻坚,附可复用的curl+jq自动化脚本
  • 2025-2026年国内打包袋品牌推荐:十大排行产品专业评测解决生鲜配送致保鲜痛点 - 品牌推荐
  • 如何选北京别墅装修公司?2026年5月推荐五家别墅装修防施工猫腻产品评测对比 - 品牌推荐
  • 单细胞黑话词典-质控图表告诉了你什么?
  • 2025-2026年国内灌装机品牌推荐:五大排行产品专业评测解决饮品灌装致液体泄漏痛点 - 品牌推荐
  • 【2026实测】毕业论文降AI太难?实用工具红黑榜与6大手工微调秘籍
  • Gemini 写作效率策略:减少返工的提示词组合技巧
  • 2026年5月国内机器人品牌推荐:十大排名产品评测夜间作业防疲劳 - 品牌推荐
  • N32G4xx单片机休眠以及RTC唤醒问题
  • 用 Excel 手动实现 MLP 前向传播 + 反向传播(完整版)
  • 【设计模式 10】抽象工厂:整体换季
  • Prompt基础与AI产品管理方法论 — 深度解析与实操设计 - hlc