如何避免CONFIG_ASSETS_PATHS变更导致的Activity重建?
问题描述
重启设备后创建LauncherActivity,后续发生配置变更时该Activity会被销毁重建。从日志中可以看到ActivityTaskManager打印了Config changes=80000000,对应Android框架中定义的CONFIG_ASSETS_PATHS(值为0x80000000)。
若LauncherActivity在不重启进程的情况下重建,会出现页面小部件重复等问题。尽管已在清单文件的android:configChanges中声明了所有可能的配置项,但无法通过该方式阻止CONFIG_ASSETS_PATHS配置变更引发的重建。
解决方案
重写onConfigurationChanged拦截配置变更
由于CONFIG_ASSETS_PATHS是框架隐藏常量,无法直接引用,可通过数值匹配的方式在Activity中拦截该配置变更,避免重建:
@Override public void onConfigurationChanged(@NonNull Configuration newConfig) { // 检查是否是CONFIG_ASSETS_PATHS变更(0x80000000) if ((newConfig.configChanges & 0x80000000) != 0) { // 仅处理资源刷新逻辑,比如重新加载壁纸相关资源 refreshWallpaperResources(); // 不要调用super.onConfigurationChanged(),避免触发Activity重建 return; } // 处理其他配置变更,调用父类方法 super.onConfigurationChanged(newConfig); }
注意事项
- 确保已在清单文件中为Activity添加
android:configChanges="orientation|screenSize|keyboardHidden|..."(包含所有常规配置项),避免其他配置变更导致的重建。 - 自定义的
refreshWallpaperResources()方法需要根据业务需求实现,比如重新加载壁纸、更新小部件状态等,保证配置变更后UI正常更新。
参考代码(框架定义)
/** * Bit in {@link #configChanges} that indicates that the activity * can itself handle asset path changes. Set from the {@link android.R.attr#configChanges} * attribute. This is not a core resource configuration, but a higher-level value, so its * constant starts at the high bits. * @hide We do not want apps handling this yet, but we do need some kind of bit for diffs. */ public static final int CONFIG_ASSETS_PATHS = 0x80000000;
参考日志
I WindowManager: finishDrawing of relaunch: Window{495529e u10 .apps.homescreen/.apps.homescreen.ui.LauncherActivity} 24ms
I ActivityTaskManager: Config changes=80000000 {1.0 ?mcc?mnc [en_GB] ldltr sw720dp w1280dp h548dp 160dpi lrg land car finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1280, 720) mAppBounds=Rect(0, 0 - 1280, 624) mMaxBounds=Rect(0, 0 - 1280, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} as.3 s.105 fontWeightAdjustment=0}
I WindowManager: Override config changes=80000000 {1.0 ?mcc?mnc [en_GB] ldltr sw720dp w1280dp h548dp 160dpi lrg land car finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1280, 720) mAppBounds=Rect(0, 0 - 1280, 624) mMaxBounds=Rect(0, 0 - 1280, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} as.3 s.105 fontWeightAdjustment=0} for displayId=0
内容的提问来源于stack exchange,提问作者Dev_Cob

