运行Android P,使用androidx 1.0.0 (minSdkVersion 17)。从我的MainActivity,我打开了我的PreferenceActivity。在这里,我将更改UI主题,并重新创建活动以获取更改:
AppCompatDelegate.setDefaultNightMode(nightMode);
recreate();更新主题后,我返回到MainActivity。在那里,主题被成功地更新。然后我重新打开PreferenceActivity并再次更改主题。
到目前为止还不错!
最后,我再次回到MainActivity。主题是未更新,如果您重复这些步骤,它将不会更新!
因此,复制的步骤似乎是:
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES),然后调用recreate()。主题更新了!AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO),然后调用recreate()。主题更新了!在从recreate()重试时,我尝试调用PreferenceActivity,但当库对主题更改作出反应时,会产生另一个问题:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (...) {
recreate();
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}当库对更新的主题没有反应时,它就会工作。否则,该活动将被重新创建两次(可能在调试时会更多),这会扼杀性能等等:
D/MainActivity: onActivityResult(): instance 1
D/MainActivity: onResume(): instance 1
D/MainActivity: onPause(): instance 1
D/MainActivity: onDestroy(): instance 1
D/MainActivity: onCreate(): instance 2
D/MainActivity: onResume(): instance 2
D/MainActivity: onPause(): instance 2
D/MainActivity: onDestroy(): instance 2
D/MainActivity: onCreate(): instance 3
D/MainActivity: onResume(): instance 3Q:,setDefaultNightMode() API是怎么回事?更重要的是,我如何成功地更新所有正在运行的活动,而不需要多次重新创建它们呢?
更新
这里有一个示例项目演示了这个问题:https://issuetracker.google.com/issues/119757688
发布于 2018-12-03 19:33:00
我找到了一个很简单的解决这个问题的方法。在这两种情况下,它都能工作;当AppCompatActivity成功地重新创建自己时,以及当它不能成功地重新创建自己时。回想一下,activity A调用活动B,其中主题被更改,然后我们返回到主题并不总是被更新的A。
活动B
在活动B (即偏好)中,我们跟踪主题的变化:
private boolean mThemeChanged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mThemeChanged = getIntent().getBooleanExtra(EXTRA_THEME_CHANGED, false);
}
private void onNightModeChanged() {
int nightMode = getNightModeFromPreferences();
if (AppCompatDelegate.getDefaultNightMode() != nightMode) {
AppCompatDelegate.setDefaultNightMode(nightMode);
getIntent().putExtra(EXTRA_THEME_CHANGED, true);
getDelegate().applyDayNight();
}
}我们将这段信息提供给呼叫活动,即Main:
@Override
public void finish() {
Intent data = new Intent();
data.putExtra(EXTRA_THEME_CHANGED, mThemeChanged);
setResult(RESULT_OK, data);
super.finish();
}活动A
然后,在活动A中,我们使用以下信息:
private boolean mShouldRecreateActivity;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ActivityResults.OPEN_SETTINGS_RESULT) {
if (data != null && data.getBooleanExtra(SetPreferenceActivity.EXTRA_THEME_CHANGED, false)) {
mShouldRecreateActivity = true;
}
}
}
@Override
protected void onResume() {
super.onResume();
if (mShouldRecreateActivity) {
recreate();
return; // No need to continue resuming!
}
}
@Override
public void recreate() {
super.recreate();
mShouldRecreateActivity = false;
}在罕见的情况下(通常是第一次),AppCompatActivity将正确地调用recreate() --我们的标志将被重置,避免了到达onResume()时额外的活动再活动。因此,这个代码应该是未来证明的。不过,我真的希望在下一个版本的androidx中解决这个问题,这样我们就可以解决这个问题了。
更新
看起来这是用AppCompat 1.1.0修复的。我不再需要这个解决办法来获得所期望的行为。
发布于 2018-11-18 00:45:58
更改夜间模式时,将模式值存储为共享首选项。
AppCompatDelegate.setDefaultNightMode(nightMode);
recreate(); //only recreate setting activity
...//store mode value, these lines are omitted,please complete yourself在其他活动onCreate()方法中:
...//get mode from share preference, these lines are omitted.
AppCompatDelegate.setDefaultNightMode(mode)//must place before super.onCreate();
super.onCreate(savedInstanceState);https://stackoverflow.com/questions/53356664
复制相似问题