Stop observing a slice view when a slice is dismissed.

In order to receive updates of slices, we make sliceLiveData observes
slice views. When a slice is dismissed, it should stop observing
the view so the view can be recycled and reused.

Fixes: 120465506
Test: robotests
Change-Id: Ie4f12e9a3e6e0e7d59d3346ab17282707047bf16
This commit is contained in:
Yi-Ling Chuang
2018-12-04 17:44:04 +08:00
parent 2efa93460c
commit 72e54c8f85
2 changed files with 25 additions and 9 deletions

View File

@@ -60,7 +60,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
private static final String TAG = "SliceCardRenderer"; private static final String TAG = "SliceCardRenderer";
@VisibleForTesting @VisibleForTesting
final Map<String, LiveData<Slice>> mSliceLiveDataMap; final Map<Uri, LiveData<Slice>> mSliceLiveDataMap;
@VisibleForTesting @VisibleForTesting
final Set<SliceViewHolder> mFlippedCardSet; final Set<SliceViewHolder> mFlippedCardSet;
@@ -95,8 +95,6 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
final SliceViewHolder cardHolder = (SliceViewHolder) holder; final SliceViewHolder cardHolder = (SliceViewHolder) holder;
final Uri uri = card.getSliceUri(); final Uri uri = card.getSliceUri();
//TODO(b/116063073): The URI check should be done earlier when we are performing final
// filtering after having the full list.
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Log.w(TAG, "Invalid uri, skipping slice: " + uri); Log.w(TAG, "Invalid uri, skipping slice: " + uri);
return; return;
@@ -106,11 +104,11 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
cardHolder.sliceView.setTag(uri); cardHolder.sliceView.setTag(uri);
//TODO(b/114009676): We will soon have a field to decide what slice mode we should set. //TODO(b/114009676): We will soon have a field to decide what slice mode we should set.
cardHolder.sliceView.setMode(SliceView.MODE_LARGE); cardHolder.sliceView.setMode(SliceView.MODE_LARGE);
LiveData<Slice> sliceLiveData = mSliceLiveDataMap.get(uri.toString()); LiveData<Slice> sliceLiveData = mSliceLiveDataMap.get(uri);
if (sliceLiveData == null) { if (sliceLiveData == null) {
sliceLiveData = SliceLiveData.fromUri(mContext, uri); sliceLiveData = SliceLiveData.fromUri(mContext, uri);
mSliceLiveDataMap.put(uri.toString(), sliceLiveData); mSliceLiveDataMap.put(uri, sliceLiveData);
} }
mCardSet.add(card); mCardSet.add(card);
@@ -146,6 +144,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card); mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card);
cardHolder.resetCard(); cardHolder.resetCard();
mFlippedCardSet.remove(cardHolder); mFlippedCardSet.remove(cardHolder);
mSliceLiveDataMap.get(card.getSliceUri()).removeObservers(mLifecycleOwner);
}); });
} }

View File

@@ -52,7 +52,7 @@ import org.robolectric.android.controller.ActivityController;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
public class SliceContextualCardRendererTest { public class SliceContextualCardRendererTest {
private static final String TEST_SLICE_URI = "content://test/test"; private static final Uri TEST_SLICE_URI = Uri.parse("content://test/test");
@Mock @Mock
private LiveData<Slice> mSliceLiveData; private LiveData<Slice> mSliceLiveData;
@@ -91,7 +91,7 @@ public class SliceContextualCardRendererTest {
@Test @Test
public void bindView_invalidScheme_sliceShouldBeNull() { public void bindView_invalidScheme_sliceShouldBeNull() {
final String sliceUri = "contet://com.android.settings.slices/action/flashlight"; final Uri sliceUri = Uri.parse("contet://com.android.settings.slices/action/flashlight");
RecyclerView.ViewHolder viewHolder = getSliceViewHolder(); RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
mRenderer.bindView(viewHolder, buildContextualCard(sliceUri)); mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
@@ -191,6 +191,23 @@ public class SliceContextualCardRendererTest {
assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder); assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder);
} }
@Test
public void viewClick_removeCard_sliceLiveDataShouldRemoveObservers() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
mRenderer.bindView(viewHolder, contextualCard);
doReturn(mController).when(mControllerRendererPool).getController(mActivity,
ContextualCard.CardType.SLICE);
card.performLongClick();
btnRemove.performClick();
assertThat(mRenderer.mSliceLiveDataMap.get(TEST_SLICE_URI).hasObservers()).isFalse();
}
@Test @Test
public void onStop_cardIsFlipped_shouldFlipBack() { public void onStop_cardIsFlipped_shouldFlipBack() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder(); final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
@@ -213,11 +230,11 @@ public class SliceContextualCardRendererTest {
return mRenderer.createViewHolder(view); return mRenderer.createViewHolder(view);
} }
private ContextualCard buildContextualCard(String sliceUri) { private ContextualCard buildContextualCard(Uri sliceUri) {
return new ContextualCard.Builder() return new ContextualCard.Builder()
.setName("test_name") .setName("test_name")
.setCardType(ContextualCard.CardType.SLICE) .setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(Uri.parse(sliceUri)) .setSliceUri(sliceUri)
.build(); .build();
} }
} }