Decrease jank in all apps physics.

By creating the spring in onCreateViewHolder and adding
in onBindViewHolder, we are able to take advantage of
RecyclerView's prefetching optimizations.

Bug: 38349031
Change-Id: Ie445039fd90ca92ae4ce1ff71c57b15f662377a8
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index d3d23ca..83c1370 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -102,7 +102,12 @@
         private SpringAnimation spring;
 
         public ViewHolder(View v) {
+            this(v, null);
+        }
+
+        public ViewHolder(View v, SpringAnimation spring) {
             super(v);
+            this.spring = spring;
         }
     }
 
@@ -285,6 +290,7 @@
 
     @Override
     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        ViewHolder viewHolder;
         switch (viewType) {
             case VIEW_TYPE_ICON:
             case VIEW_TYPE_PREDICTION_ICON:
@@ -298,16 +304,19 @@
 
                 // Ensure the all apps icon height matches the workspace icons
                 icon.getLayoutParams().height = getCellSize().y;
-                return new ViewHolder(icon);
+                viewHolder = new ViewHolder(icon);
+                break;
             case VIEW_TYPE_DISCOVERY_ITEM:
                 AppDiscoveryItemView appDiscoveryItemView = (AppDiscoveryItemView) mLayoutInflater
                         .inflate(R.layout.all_apps_discovery_item, parent, false);
                 appDiscoveryItemView.init(mIconClickListener, mLauncher.getAccessibilityDelegate(),
                         mIconLongClickListener);
-                return new ViewHolder(appDiscoveryItemView);
+                viewHolder = new ViewHolder(appDiscoveryItemView);
+                break;
             case VIEW_TYPE_EMPTY_SEARCH:
-                return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search,
+                viewHolder = new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search,
                         parent, false));
+                break;
             case VIEW_TYPE_SEARCH_MARKET:
                 View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
                         parent, false);
@@ -317,21 +326,30 @@
                         mLauncher.startActivitySafely(v, mMarketSearchIntent, null);
                     }
                 });
-                return new ViewHolder(searchMarketView);
+                viewHolder = new ViewHolder(searchMarketView);
+                break;
             case VIEW_TYPE_SEARCH_DIVIDER:
-                return new ViewHolder(mLayoutInflater.inflate(
+                viewHolder = new ViewHolder(mLayoutInflater.inflate(
                         R.layout.all_apps_search_divider, parent, false));
+                break;
             case VIEW_TYPE_APPS_LOADING_DIVIDER:
                 View loadingDividerView = mLayoutInflater.inflate(
                         R.layout.all_apps_discovery_loading_divider, parent, false);
-                return new ViewHolder(loadingDividerView);
+                viewHolder = new ViewHolder(loadingDividerView);
+                break;
             case VIEW_TYPE_PREDICTION_DIVIDER:
             case VIEW_TYPE_SEARCH_MARKET_DIVIDER:
-                return new ViewHolder(mLayoutInflater.inflate(
+                viewHolder = new ViewHolder(mLayoutInflater.inflate(
                         R.layout.all_apps_divider, parent, false));
+                break;
             default:
                 throw new RuntimeException("Unexpected view type");
         }
+
+        if (FeatureFlags.LAUNCHER3_PHYSICS && isViewType(viewType, VIEW_TYPE_MASK_HAS_SPRINGS)) {
+            viewHolder.spring = mSpringAnimationHandler.createSpringAnimation(viewHolder.itemView);
+        }
+        return viewHolder;
     }
 
     private Point getCellSize() {
@@ -340,7 +358,8 @@
 
     @Override
     public void onBindViewHolder(ViewHolder holder, int position) {
-        switch (holder.getItemViewType()) {
+        int viewType = holder.getItemViewType();
+        switch (viewType) {
             case VIEW_TYPE_ICON:
             case VIEW_TYPE_PREDICTION_ICON:
                 AppInfo info = mApps.getAdapterItems().get(position).appInfo;
@@ -377,21 +396,16 @@
                 // nothing to do
                 break;
         }
+        if (FeatureFlags.LAUNCHER3_PHYSICS && isViewType(viewType, VIEW_TYPE_MASK_HAS_SPRINGS)) {
+            holder.spring = mSpringAnimationHandler.add(holder.itemView, position, mApps,
+                    mAppsPerRow, holder.spring);
+        }
         if (mBindViewCallback != null) {
             mBindViewCallback.onBindView(holder);
         }
     }
 
     @Override
-    public void onViewAttachedToWindow(ViewHolder holder) {
-        int type = holder.getItemViewType();
-        if (FeatureFlags.LAUNCHER3_PHYSICS && isViewType(type, VIEW_TYPE_MASK_HAS_SPRINGS)) {
-            holder.spring = mSpringAnimationHandler.add(holder.itemView,
-                    holder.getAdapterPosition(), mApps, mAppsPerRow, holder.spring);
-        }
-    }
-
-    @Override
     public void onViewDetachedFromWindow(ViewHolder holder) {
         int type = holder.getItemViewType();
         if (FeatureFlags.LAUNCHER3_PHYSICS && isViewType(type, VIEW_TYPE_MASK_HAS_SPRINGS)) {
diff --git a/src/com/android/launcher3/anim/SpringAnimationHandler.java b/src/com/android/launcher3/anim/SpringAnimationHandler.java
index 488657c..92acfb8 100644
--- a/src/com/android/launcher3/anim/SpringAnimationHandler.java
+++ b/src/com/android/launcher3/anim/SpringAnimationHandler.java
@@ -178,7 +178,7 @@
         return mDirection == Y_DIRECTION;
     }
 
-    private SpringAnimation createSpringAnimation(View view) {
+    public SpringAnimation createSpringAnimation(View view) {
         DynamicAnimation.ViewProperty property = isVerticalDirection()
                 ? DynamicAnimation.TRANSLATION_Y
                 : DynamicAnimation.TRANSLATION_X;