Merge "Fix OutOfBounds issue on getFocusedChild" into ub-launcher3-master
diff --git a/src/com/android/launcher3/allapps/search/LiveSearchManager.java b/src/com/android/launcher3/allapps/search/LiveSearchManager.java
index e8a00d9..ec33908 100644
--- a/src/com/android/launcher3/allapps/search/LiveSearchManager.java
+++ b/src/com/android/launcher3/allapps/search/LiveSearchManager.java
@@ -23,9 +23,14 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.UserHandle;
 
+import androidx.lifecycle.LiveData;
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceLiveData;
+
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.util.ComponentKey;
@@ -42,7 +47,9 @@
 
     private final Launcher mLauncher;
     private final AppWidgetManager mAppWidgetManger;
-    private HashMap<ComponentKey, SearchWidgetInfoContainer> mWidgetPlaceholders = new HashMap<>();
+    private final HashMap<ComponentKey, SearchWidgetInfoContainer> mWidgetPlaceholders =
+            new HashMap<>();
+    private final HashMap<Uri, LiveData<Slice>> mUriSliceMap = new HashMap<>();
     private SearchWidgetHost mSearchWidgetHost;
 
     public LiveSearchManager(Launcher launcher) {
@@ -88,6 +95,20 @@
     }
 
     /**
+     * Creates {@link LiveData<Slice>} from Slice Uri. Caches created live data to be reused
+     * within the same search session. Removes previous observers when new SliceView request a
+     * live data for observation.
+     */
+    public LiveData<Slice> getSliceForUri(Uri sliceUri) {
+        LiveData<Slice> sliceLiveData = mUriSliceMap.getOrDefault(sliceUri, null);
+        if (sliceLiveData == null) {
+            sliceLiveData = SliceLiveData.fromUri(mLauncher, sliceUri);
+            mUriSliceMap.put(sliceUri, sliceLiveData);
+        }
+        return sliceLiveData;
+    }
+
+    /**
      * Start search session
      */
     public void start() {
@@ -109,6 +130,10 @@
             mWidgetPlaceholders.clear();
             mSearchWidgetHost = null;
         }
+        for (LiveData<Slice> liveData : mUriSliceMap.values()) {
+            liveData.removeObservers(mLauncher);
+        }
+        mUriSliceMap.clear();
     }
 
     static class SearchWidgetHost extends AppWidgetHost {
diff --git a/src/com/android/launcher3/views/SearchResultSettingsSlice.java b/src/com/android/launcher3/views/SearchResultSettingsSlice.java
index 2d726e7..29e6c1b 100644
--- a/src/com/android/launcher3/views/SearchResultSettingsSlice.java
+++ b/src/com/android/launcher3/views/SearchResultSettingsSlice.java
@@ -28,7 +28,6 @@
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.widget.EventInfo;
-import androidx.slice.widget.SliceLiveData;
 import androidx.slice.widget.SliceView;
 
 import com.android.launcher3.Launcher;
@@ -54,7 +53,7 @@
     private View mIcon;
     private LiveData<Slice> mSliceLiveData;
     private SearchTarget mSearchTarget;
-    private Launcher mLauncher;
+    private final Launcher mLauncher;
 
     public SearchResultSettingsSlice(Context context) {
         this(context, null, 0);
@@ -84,7 +83,7 @@
         reset();
         mSearchTarget = searchTarget;
         try {
-            mSliceLiveData = SliceLiveData.fromUri(mLauncher, getSliceUri());
+            mSliceLiveData = mLauncher.getLiveSearchManager().getSliceForUri(getSliceUri());
             mSliceLiveData.observe(mLauncher, mSliceView);
         } catch (Exception ex) {
             Log.e(TAG, "unable to bind slice", ex);