Miscellaneous fixes

-Fix fragment animation on exit
-Use DateUtils.RelativeTimeSpanString instead of SimpleDateFormat
-Fix RecyclerView ordering and remove arbitrary "25" pre-seeding
-Cancel evaluation for only the id corresponding to the recycled
ViewHolder

Fixes: 32918645
Fixes: 32945018
Fixes: 33000429

Change-Id: I55e3a101a02aec8fe03d43ad0b60343d1fa36940
diff --git a/src/com/android/calculator2/HistoryAdapter.java b/src/com/android/calculator2/HistoryAdapter.java
index 169e34f..ca5509c 100644
--- a/src/com/android/calculator2/HistoryAdapter.java
+++ b/src/com/android/calculator2/HistoryAdapter.java
@@ -39,13 +39,12 @@
 
     private List<HistoryItem> mDataSet;
 
-    private boolean mHasCurrentExpression = true;
-
     public HistoryAdapter(Calculator calculator, ArrayList<HistoryItem> dataSet,
             String currentExpressionDescription) {
         mEvaluator = Evaluator.getInstance(calculator);
         mDataSet = dataSet;
         mCurrentExpressionDescription = currentExpressionDescription;
+        setHasStableIds(true);
     }
 
     @Override
@@ -71,41 +70,44 @@
 
         holder.mFormula.setText(item.getFormula());
         // Note: HistoryItems that are not the current expression will always have interesting ops.
-        holder.mResult.setEvaluator(mEvaluator, item.getId());
-        if (mHasCurrentExpression && position == 0) {
+        holder.mResult.setEvaluator(mEvaluator, item.getEvaluatorIndex());
+        if (item.getEvaluatorIndex() == Evaluator.MAIN_INDEX) {
             holder.mDate.setText(mCurrentExpressionDescription);
             holder.mDate.setContentDescription(mCurrentExpressionDescription);
         } else {
             holder.mDate.setText(item.getDateString());
-            holder.mDate.setContentDescription(item.getDateDescription());
         }
     }
 
-    public void setHasCurrentExpression(boolean has) {
-        mHasCurrentExpression = has;
-    }
-
     @Override
     public void onViewRecycled(ViewHolder holder) {
+        if (holder.getItemViewType() == EMPTY_VIEW_TYPE) {
+            return;
+        }
+        mEvaluator.cancel(holder.getItemId(), true);
+
         holder.mDate.setContentDescription(null);
         holder.mDate.setText(null);
         holder.mFormula.setText(null);
         holder.mResult.setText(null);
 
-        // TODO: Only cancel the calculation for the recycled view
-        mEvaluator.cancelAll(true);
-
         super.onViewRecycled(holder);
     }
 
     @Override
+    public long getItemId(int position) {
+        return mDataSet.get(position).getEvaluatorIndex();
+    }
+
+    @Override
     public int getItemViewType(int position) {
         HistoryItem item = mDataSet.get(position);
 
         // Continue to lazy-fill the data set
         if (item == null) {
-            item = new HistoryItem(position, mEvaluator.getTimeStamp(position),
-                    mEvaluator.getExprAsSpannable(position));
+            final int evaluatorIndex = getEvaluatorIndex(position);
+            item = new HistoryItem(evaluatorIndex, mEvaluator.getTimeStamp(evaluatorIndex),
+                    mEvaluator.getExprAsSpannable(evaluatorIndex));
             mDataSet.set(position, item);
         }
         return item.isEmptyView() ? EMPTY_VIEW_TYPE : HISTORY_VIEW_TYPE;
@@ -120,6 +122,15 @@
         mDataSet = dataSet;
     }
 
+    private int getEvaluatorIndex(int position) {
+        if (EvaluatorStateUtils.isDisplayEmpty(mEvaluator)) {
+            return (int) mEvaluator.getMaxIndex() - position;
+        } else {
+            // Account for the additional "Current Expression" with the +1.
+            return (int) mEvaluator.getMaxIndex() - position + 1;
+        }
+    }
+
     public static class ViewHolder extends RecyclerView.ViewHolder {
 
         private TextView mDate;