Defer some work until after workspace fade-in

Defer:
- Setting all apps
- Setting widgets

Also set the launcher-loader thread to THREAD_PRIORITY_BACKGROUND
for the duration of the animation.

Bug: 37965432
Change-Id: I8364940805b84aecb8353a473ab4d575c27bfec4
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7c25861..615ec47 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -144,6 +144,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 /**
  * Default launcher application.
@@ -1855,6 +1856,8 @@
 
         LauncherAnimUtils.onDestroyActivity();
 
+        clearPendingBinds();
+
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onDestroy();
         }
@@ -3705,6 +3708,13 @@
         }
 
         if (mAppsView != null) {
+            Executor pendingExecutor = getPendingExecutor();
+            if (pendingExecutor != null && mState != State.APPS) {
+                // Wait until the fade in animation has finished before setting all apps list.
+                mTmpAppsList = apps;
+                pendingExecutor.execute(mBindAllApplicationsRunnable);
+                return;
+            }
             mAppsView.setApps(apps);
         }
         if (mLauncherCallbacks != null) {
@@ -3713,6 +3723,14 @@
     }
 
     /**
+     * Returns an Executor that will run after the launcher is first drawn (including after the
+     * initial fade in animation). Returns null if the first draw has already occurred.
+     */
+    public @Nullable Executor getPendingExecutor() {
+        return mPendingExecutor != null && mPendingExecutor.canQueue() ? mPendingExecutor : null;
+    }
+
+    /**
      * Copies LauncherModel's map of activities to shortcut ids to Launcher's. This is necessary
      * because LauncherModel's map is updated in the background, while Launcher runs on the UI.
      */
@@ -3904,6 +3922,12 @@
         }
 
         if (mWidgetsView != null && allWidgets != null) {
+            Executor pendingExecutor = getPendingExecutor();
+            if (pendingExecutor != null && mState != State.WIDGETS) {
+                mAllWidgets = allWidgets;
+                pendingExecutor.execute(mBindAllWidgetsRunnable);
+                return;
+            }
             mWidgetsView.setWidgets(allWidgets);
             mAllWidgets = null;
         }