SliceLiveData should remove observers.

As positions of items will be changed, new sliceViews will be created.
SliceLiveData has been set to observe a certain old sliceView. When the
page is re-launched, we cannot garantee we always get the same
sliceView, which means the sliceLiveData may be still observing a sliveView that
is no longer applicable. This will lead to broken slices.
Hence, we need to remove observers first then make it observes a new sliceView.

Bug: 117922624
Test: robotests, visual
Change-Id: I59368a6ce5fa84487c9a4788b970fdc074a0c2a9
This commit is contained in:
Emily Chuang
2018-10-18 21:01:25 +08:00
parent 4ae062b7c8
commit 8b680a988d
2 changed files with 25 additions and 7 deletions

View File

@@ -91,14 +91,16 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
if (sliceLiveData == null) {
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
sliceLiveData.observe(mLifecycleOwner, slice -> {
if (slice == null) {
Log.w(TAG, "Slice is null");
}
cardHolder.sliceView.setSlice(slice);
});
}
sliceLiveData.removeObservers(mLifecycleOwner);
sliceLiveData.observe(mLifecycleOwner, slice -> {
if (slice == null) {
Log.w(TAG, "Slice is null");
}
cardHolder.sliceView.setSlice(slice);
});
// Set this listener so we can log the interaction users make on the slice
cardHolder.sliceView.setOnSliceActionListener(this);
}

View File

@@ -18,7 +18,7 @@ package com.android.settings.homepage.slices;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.net.Uri;
@@ -26,8 +26,10 @@ import android.view.LayoutInflater;
import android.view.View;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.slice.Slice;
import com.android.settings.homepage.ContextualCard;
import com.android.settings.homepage.PersonalSettingsFragment;
@@ -36,12 +38,16 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class SliceContextualCardRendererTest {
@Mock
private LiveData<Slice> mSliceLiveData;
private Context mContext;
private SliceContextualCardRenderer mRenderer;
private LifecycleOwner mLifecycleOwner;
@@ -96,6 +102,16 @@ public class SliceContextualCardRendererTest {
assertThat(mRenderer.mSliceLiveDataMap.get(sliceUri).hasObservers()).isTrue();
}
@Test
public void bindview_sliceLiveDataShouldRemoveObservers() {
final String sliceUri = "content://com.android.settings.slices/action/flashlight";
mRenderer.mSliceLiveDataMap.put(sliceUri, mSliceLiveData);
mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri));
verify(mSliceLiveData).removeObservers(mLifecycleOwner);
}
private RecyclerView.ViewHolder getSliceViewHolder() {
final int viewType = mRenderer.getViewType();
final RecyclerView recyclerView = new RecyclerView(mContext);