Change underlying preferenceControllers to an ArrayMap of Lists.

Previously, DashboardFragment stores preference controllers in an
ArrayMap of <Class, AbstractPreferenceController>. Thus when there are
multiple controllers of same class (ie. multiple
PreferenceCategoryControllers), they cannot be stored simultaneously.
This changes the value to a List so we can store multiple controllers of
the same Class without extraneous sub-classing.

Bug: 70949662
Test: All existing tests still pass.
Added
DashboardFragmentTest#testPreferenceControllerSetter_shouldAddAndNotReplace
and DashboardFragmentTest#updateState_doesNotSkipControllersOfSameClass.
Change-Id: I397e8c91977ea1180d48a3af75dd4058bf1175c0
This commit is contained in:
Ben Lin
2017-12-21 17:32:34 -08:00
parent e0f8db5d64
commit 9275177002
3 changed files with 75 additions and 26 deletions

View File

@@ -54,7 +54,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
SummaryLoader.SummaryConsumer { SummaryLoader.SummaryConsumer {
private static final String TAG = "DashboardFragment"; private static final String TAG = "DashboardFragment";
private final Map<Class, AbstractPreferenceController> mPreferenceControllers = private final Map<Class, List<AbstractPreferenceController>> mPreferenceControllers =
new ArrayMap<>(); new ArrayMap<>();
private final Set<String> mDashboardTilePrefKeys = new ArraySet<>(); private final Set<String> mDashboardTilePrefKeys = new ArraySet<>();
@@ -156,16 +156,19 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
@Override @Override
public boolean onPreferenceTreeClick(Preference preference) { public boolean onPreferenceTreeClick(Preference preference) {
Collection<AbstractPreferenceController> controllers = mPreferenceControllers.values(); Collection<List<AbstractPreferenceController>> controllers =
mPreferenceControllers.values();
// If preference contains intent, log it before handling. // If preference contains intent, log it before handling.
mMetricsFeatureProvider.logDashboardStartIntent( mMetricsFeatureProvider.logDashboardStartIntent(
getContext(), preference.getIntent(), getMetricsCategory()); getContext(), preference.getIntent(), getMetricsCategory());
// Give all controllers a chance to handle click. // Give all controllers a chance to handle click.
for (AbstractPreferenceController controller : controllers) { for (List<AbstractPreferenceController> controllerList : controllers) {
for (AbstractPreferenceController controller : controllerList) {
if (controller.handlePreferenceTreeClick(preference)) { if (controller.handlePreferenceTreeClick(preference)) {
return true; return true;
} }
} }
}
return super.onPreferenceTreeClick(preference); return super.onPreferenceTreeClick(preference);
} }
@@ -189,12 +192,23 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
protected abstract int getPreferenceScreenResId(); protected abstract int getPreferenceScreenResId();
protected <T extends AbstractPreferenceController> T getPreferenceController(Class<T> clazz) { protected <T extends AbstractPreferenceController> T getPreferenceController(Class<T> clazz) {
AbstractPreferenceController controller = mPreferenceControllers.get(clazz); List<AbstractPreferenceController> controllerList = mPreferenceControllers.get(clazz);
return (T) controller; if (controllerList != null) {
if (controllerList.size() > 1) {
Log.w(TAG, "Multiple controllers of Class " + clazz.getSimpleName()
+ " found, returning first one.");
}
return (T) controllerList.get(0);
}
return null;
} }
protected void addPreferenceController(AbstractPreferenceController controller) { protected void addPreferenceController(AbstractPreferenceController controller) {
mPreferenceControllers.put(controller.getClass(), controller); if (mPreferenceControllers.get(controller.getClass()) == null) {
mPreferenceControllers.put(controller.getClass(), new ArrayList<>());
}
mPreferenceControllers.get(controller.getClass()).add(controller);
} }
/** /**
@@ -249,19 +263,19 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
} }
addPreferencesFromResource(resId); addPreferencesFromResource(resId);
final PreferenceScreen screen = getPreferenceScreen(); final PreferenceScreen screen = getPreferenceScreen();
Collection<AbstractPreferenceController> controllers = mPreferenceControllers.values(); mPreferenceControllers.values().stream().flatMap(Collection::stream).forEach(
for (AbstractPreferenceController controller : controllers) { controller -> controller.displayPreference(screen));
controller.displayPreference(screen);
}
} }
/** /**
* Update state of each preference managed by PreferenceController. * Update state of each preference managed by PreferenceController.
*/ */
protected void updatePreferenceStates() { protected void updatePreferenceStates() {
Collection<AbstractPreferenceController> controllers = mPreferenceControllers.values();
final PreferenceScreen screen = getPreferenceScreen(); final PreferenceScreen screen = getPreferenceScreen();
for (AbstractPreferenceController controller : controllers) { Collection<List<AbstractPreferenceController>> controllerLists =
mPreferenceControllers.values();
for (List<AbstractPreferenceController> controllerList : controllerLists) {
for (AbstractPreferenceController controller : controllerList) {
if (!controller.isAvailable()) { if (!controller.isAvailable()) {
continue; continue;
} }
@@ -276,6 +290,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
controller.updateState(preference); controller.updateState(preference);
} }
} }
}
/** /**
* Refresh all preference items, including both static prefs from xml, and dynamic items from * Refresh all preference items, including both static prefs from xml, and dynamic items from

View File

@@ -90,6 +90,19 @@ public class DashboardFragmentTest {
assertThat(controller).isSameAs(retrievedController); assertThat(controller).isSameAs(retrievedController);
} }
@Test
public void testPreferenceControllerSetter_shouldAddAndNotReplace() {
final TestPreferenceController controller1 = new TestPreferenceController(mContext);
mTestFragment.addPreferenceController(controller1);
final TestPreferenceController controller2 = new TestPreferenceController(mContext);
mTestFragment.addPreferenceController(controller2);
final TestPreferenceController retrievedController = mTestFragment.getPreferenceController
(TestPreferenceController.class);
assertThat(controller1).isSameAs(retrievedController);
}
@Test @Test
public void displayTilesAsPreference_shouldAddTilesWithIntent() { public void displayTilesAsPreference_shouldAddTilesWithIntent() {
when(mFakeFeatureFactory.dashboardFeatureProvider when(mFakeFeatureFactory.dashboardFeatureProvider
@@ -145,6 +158,23 @@ public class DashboardFragmentTest {
verify(mockController2).getPreferenceKey(); verify(mockController2).getPreferenceKey();
} }
@Test
public void updateState_doesNotSkipControllersOfSameClass() {
final AbstractPreferenceController mockController1 =
mock(AbstractPreferenceController.class);
final AbstractPreferenceController mockController2 =
mock(AbstractPreferenceController.class);
mTestFragment.addPreferenceController(mockController1);
mTestFragment.addPreferenceController(mockController2);
when(mockController1.isAvailable()).thenReturn(true);
when(mockController2.isAvailable()).thenReturn(true);
mTestFragment.updatePreferenceStates();
verify(mockController1).getPreferenceKey();
verify(mockController2).getPreferenceKey();
}
@Test @Test
public void tintTileIcon_hasMetadata_shouldReturnIconTintableMetadata() { public void tintTileIcon_hasMetadata_shouldReturnIconTintableMetadata() {
final Tile tile = new Tile(); final Tile tile = new Tile();

View File

@@ -33,6 +33,8 @@ import org.junit.runner.RunWith;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@@ -55,10 +57,12 @@ public class ScreenLockSettingsTest {
@Test @Test
public void onOwnerInfoUpdated_shouldUpdateOwnerInfoController() { public void onOwnerInfoUpdated_shouldUpdateOwnerInfoController() {
final Map<Class, AbstractPreferenceController> preferenceControllers = final Map<Class, List<AbstractPreferenceController>> preferenceControllers =
ReflectionHelpers.getField(mSettings, "mPreferenceControllers"); ReflectionHelpers.getField(mSettings, "mPreferenceControllers");
final OwnerInfoPreferenceController controller = mock(OwnerInfoPreferenceController.class); final OwnerInfoPreferenceController controller = mock(OwnerInfoPreferenceController.class);
preferenceControllers.put(OwnerInfoPreferenceController.class, controller); List<AbstractPreferenceController> controllerList = new ArrayList<>();
controllerList.add(controller);
preferenceControllers.put(OwnerInfoPreferenceController.class, controllerList);
mSettings.onOwnerInfoUpdated(); mSettings.onOwnerInfoUpdated();