优化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是鼠标和键盘在断开蓝牙过程中重新启动了Activity2是由于设备配置太低主线程已经处理不过来突如其来的大量刷新任务其实在加日志查看的过程中由于Settings/SystemUI设计的臃肿性导致断开蓝牙后有15个组件一起刷新所以导致主线程根本处理不过来3.解决方案首要解决的就是在断开蓝牙过程中Activity重启现象在AndroidManifest中对应的Activity添加如下标识符让其在蓝牙断开连接过程中不会重新启动Activityandroid:configChangesorientation|screenSize|keyboard|keyboardHidden|navigation这样我们的耗时过长问题基本解决了但是发现还是会卡顿水波纹显示不出来其实从日志中这时我们从日志中查看onCreate的打印没有了但是还是会打印出来Skipped 48 frames! The application may be doing too much work on its main thread.其实上述虽然我们让其不重新启动了但是臃肿(15个组件一起更新)的问题还是存在的所以此时我们需要排优先级先把点击断开过程的水波纹显示出来然后开始进行断开流程这里我们用view.postDelay方式即可此时优化的差不多了然后我想进一步优化就把一些可以放在子线程的方法给放到子线程中了如下是最终的patchdiff --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:exportedfalse android:themestyle/Theme.SubSettings android:knownActivityEmbeddingCertsarray/config_known_host_certs - android:taskAffinitycom.android.settings.root / android:taskAffinitycom.android.settings.root android:configChangesorientation|screenSize|keyboard|keyboardHidden|navigation / activity android:name.Settings$CreateShortcutActivity android:exportedtrue -4533,6 4534,7 activity android:nameSettings$BluetoothDeviceDetailActivity android:labelstring/device_details_title android:exportedtrue android:configChangesorientation|screenSize|keyboard|keyboardHidden|navigation android:permissionandroid.permission.BLUETOOTH_CONNECT intent-filter android:priority1 action android:namecom.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; }