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:
@@ -91,14 +91,16 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
|
|||||||
if (sliceLiveData == null) {
|
if (sliceLiveData == null) {
|
||||||
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
|
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
|
||||||
mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
|
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
|
// Set this listener so we can log the interaction users make on the slice
|
||||||
cardHolder.sliceView.setOnSliceActionListener(this);
|
cardHolder.sliceView.setOnSliceActionListener(this);
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ package com.android.settings.homepage.slices;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
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.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -26,8 +26,10 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.slice.Slice;
|
||||||
|
|
||||||
import com.android.settings.homepage.ContextualCard;
|
import com.android.settings.homepage.ContextualCard;
|
||||||
import com.android.settings.homepage.PersonalSettingsFragment;
|
import com.android.settings.homepage.PersonalSettingsFragment;
|
||||||
@@ -36,12 +38,16 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
public class SliceContextualCardRendererTest {
|
public class SliceContextualCardRendererTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LiveData<Slice> mSliceLiveData;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private SliceContextualCardRenderer mRenderer;
|
private SliceContextualCardRenderer mRenderer;
|
||||||
private LifecycleOwner mLifecycleOwner;
|
private LifecycleOwner mLifecycleOwner;
|
||||||
@@ -96,6 +102,16 @@ public class SliceContextualCardRendererTest {
|
|||||||
assertThat(mRenderer.mSliceLiveDataMap.get(sliceUri).hasObservers()).isTrue();
|
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() {
|
private RecyclerView.ViewHolder getSliceViewHolder() {
|
||||||
final int viewType = mRenderer.getViewType();
|
final int viewType = mRenderer.getViewType();
|
||||||
final RecyclerView recyclerView = new RecyclerView(mContext);
|
final RecyclerView recyclerView = new RecyclerView(mContext);
|
||||||
|
Reference in New Issue
Block a user