Improve lifecycle of ZenModeFragment & friends

* Don't keep Settings observers longer than start-stop.
* Only call updateState() once on controllers during create->start->resume.
* Remove some duplicate controller update methods from ZenModesFragmentBase (we can directly call DashboardFragment's).
* Don't update controllers if unrelated modes were changed.
* Extract ZenSettingsObserver for use in the link tile later.
* Add tests.

Fixes: 353946788
Test: atest com.android.settings.notification.modes
Flag: android.app.modes_ui
Change-Id: I64b51714d699b5c3a592a76fcb615d2999998829
This commit is contained in:
Matías Hernández
2024-07-29 17:45:27 +02:00
parent cadfc0187d
commit b8b897e552
11 changed files with 577 additions and 231 deletions

View File

@@ -21,14 +21,11 @@ import static com.google.common.base.Preconditions.checkState;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -39,7 +36,6 @@ import com.android.settingslib.notification.modes.ZenModesBackend;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.List;
/**
@@ -79,7 +75,11 @@ public abstract class ZenModeEditNameIconFragmentBase extends DashboardFragment
? icicle.getParcelable(MODE_KEY, ZenMode.class)
: onCreateInstantiateZenMode();
if (mZenMode == null) {
if (mZenMode != null) {
for (var controller : getZenPreferenceControllers()) {
controller.setZenMode(mZenMode);
}
} else {
finish();
}
}
@@ -110,58 +110,32 @@ public abstract class ZenModeEditNameIconFragmentBase extends DashboardFragment
);
}
private Iterable<AbstractZenModePreferenceController> getZenPreferenceControllers() {
return getPreferenceControllers().stream()
.flatMap(List::stream)
.filter(AbstractZenModePreferenceController.class::isInstance)
.map(AbstractZenModePreferenceController.class::cast)
.toList();
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
@Nullable
ZenMode getZenMode() {
return mZenMode;
}
@Override
public void onStart() {
super.onStart();
updateControllers();
}
@VisibleForTesting
final void setModeName(String name) {
checkNotNull(mZenMode).getRule().setName(Strings.nullToEmpty(name));
updateControllers(); // Updates confirmation button.
forceUpdatePreferences(); // Updates confirmation button.
}
@VisibleForTesting
final void setModeIcon(@DrawableRes int iconResId) {
checkNotNull(mZenMode).getRule().setIconResId(iconResId);
updateControllers(); // Updates icon at the top.
forceUpdatePreferences(); // Updates icon at the top.
}
protected void updateControllers() {
PreferenceScreen screen = getPreferenceScreen();
Collection<List<AbstractPreferenceController>> controllers = getPreferenceControllers();
if (mZenMode == null || screen == null || controllers == null) {
return;
}
for (List<AbstractPreferenceController> list : controllers) {
for (AbstractPreferenceController controller : list) {
try {
final String key = controller.getPreferenceKey();
final Preference preference = screen.findPreference(key);
if (preference != null) {
AbstractZenModePreferenceController zenController =
(AbstractZenModePreferenceController) controller;
zenController.updateZenMode(preference, mZenMode);
} else {
Log.d(getLogTag(),
String.format("Cannot find preference with key %s in Controller %s",
key, controller.getClass().getSimpleName()));
}
controller.displayPreference(screen);
} catch (ClassCastException e) {
// Skip any controllers that aren't AbstractZenModePreferenceController.
Log.d(getLogTag(), "Could not cast: " + controller.getClass().getSimpleName());
}
}
}
}
@VisibleForTesting
final void saveMode() {