Android P使用androidx 1.0.0(minSdkVersion 17)运行。从我MainActivity打开我的PreferenceActivity。在那里,我更改了UI主题,还重新创建了活动以获取更改:
AppCompatDelegate.setDefaultNightMode(nightMode);
recreate();
Run Code Online (Sandbox Code Playgroud)
更新主题后,我返回MainActivity。在那里,主题已成功更新。然后,我重新打开PreferenceActivity并再次更改主题。
到目前为止,一切都很好!
最后,我MainActivity再次回到。会议的主题是不更新,如果你重复这些步骤也不会更新!
因此,重现步骤似乎是:
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES)和recreate()。主题已更新!AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO)和recreate()。主题已更新!我打过电话recreate()从returing时PreferenceActivity而是产生另一个问题,当库并在主题的变化作出反应:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (...) {
recreate();
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
Run Code Online (Sandbox Code Playgroud)
当库对更新的主题不起作用时,该方法有效。否则,该活动将被重新创建两次(调试时可能会重新创建),这会降低性能等:
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 3
Run Code Online (Sandbox Code Playgroud)
问:这是怎么回事用setDefaultNightMode()API?更重要的是,如何才能成功更新所有正在运行的活动,而又没有多次重新创建活动的风险?
这里有一个示例项目演示了这个问题:https : //issuetracker.google.com/issues/119757688
当您更改夜间模式时,请将模式值存储到共享首选项。
AppCompatDelegate.setDefaultNightMode(nightMode);
recreate(); //only recreate setting activity
...//store mode value, these lines are omitted,please complete yourself
Run Code Online (Sandbox Code Playgroud)
在其他活动的 onCreate() 方法中:
...//get mode from share preference, these lines are omitted.
AppCompatDelegate.setDefaultNightMode(mode)//must place before super.onCreate();
super.onCreate(savedInstanceState);
Run Code Online (Sandbox Code Playgroud)
我找到了解决这个问题的一个非常简单的方法。它在两种情况下都有效;何时AppCompatActivity成功重新创建自身以及何时失败。回想一下,活动调用主题更改的A活动,然后我们返回到主题并不总是更新的地方。BA
在活动中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();
}
}
Run Code Online (Sandbox Code Playgroud)
我们将这条信息提供给调用活动,即 Main:
@Override
public void finish() {
Intent data = new Intent();
data.putExtra(EXTRA_THEME_CHANGED, mThemeChanged);
setResult(RESULT_OK, data);
super.finish();
}
Run Code Online (Sandbox Code Playgroud)
然后在活动中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;
}
Run Code Online (Sandbox Code Playgroud)
在极少数情况下(通常是第一次),AppCompatActivity正确调用recreate()我们的标志将被重置,以避免当我们到达 时再次重新创建活动onResume()。因此,这段代码应该是面向未来的。不过,我真的希望这个问题能够在下一个版本中得到解决androidx,让我们能够摆脱这个解决方法。
看起来这个问题已经被修复了AppCompat 1.1.0。我不再需要这种解决方法来获得所需的行为。
| 归档时间: |
|
| 查看次数: |
1075 次 |
| 最近记录: |