Merge "Let the framework manage fragments" into jb-ub-mail-ur8
diff --git a/src/com/android/ex/photo/PhotoViewActivity.java b/src/com/android/ex/photo/PhotoViewActivity.java
index b412246..fad1b31 100644
--- a/src/com/android/ex/photo/PhotoViewActivity.java
+++ b/src/com/android/ex/photo/PhotoViewActivity.java
@@ -150,7 +150,7 @@
         }
 
         // projection for the query; optional
-        // I.f not set, the default projection is used.
+        // If not set, the default projection is used.
         // This projection must include the columns from the default projection.
         if (mIntent.hasExtra(Intents.EXTRA_PROJECTION)) {
             mProjection = mIntent.getStringArrayExtra(Intents.EXTRA_PROJECTION);
@@ -159,24 +159,26 @@
         }
 
         // Set the current item from the intent if wasn't in the saved instance
-        if (mIntent.hasExtra(Intents.EXTRA_PHOTO_INDEX) && currentItem < 0) {
-            currentItem = mIntent.getIntExtra(Intents.EXTRA_PHOTO_INDEX, -1);
+        if (currentItem < 0) {
+            if (mIntent.hasExtra(Intents.EXTRA_PHOTO_INDEX)) {
+                currentItem = mIntent.getIntExtra(Intents.EXTRA_PHOTO_INDEX, -1);
+            }
+            if (mIntent.hasExtra(Intents.EXTRA_INITIAL_PHOTO_URI)) {
+                mInitialPhotoUri = mIntent.getStringExtra(Intents.EXTRA_INITIAL_PHOTO_URI);
+            }
         }
-        if (mIntent.hasExtra(Intents.EXTRA_INITIAL_PHOTO_URI) && currentItem < 0) {
-            mInitialPhotoUri = mIntent.getStringExtra(Intents.EXTRA_INITIAL_PHOTO_URI);
-        }
-
         // Set the max initial scale, defaulting to 1x
         mMaxInitialScale = mIntent.getFloatExtra(Intents.EXTRA_MAX_INITIAL_SCALE, 1.0f);
 
-        mPhotoIndex = currentItem;
+        // If we still have a negative current item, set it to zero
+        mPhotoIndex = Math.max(currentItem, 0);
         mIsEmpty = true;
 
         setContentView(R.layout.photo_activity_view);
 
         // Create the adapter and add the view pager
-        mAdapter = createPhotoPagerAdapter(this, getSupportFragmentManager(),
-            null, mMaxInitialScale);
+        mAdapter =
+                createPhotoPagerAdapter(this, getSupportFragmentManager(), null, mMaxInitialScale);
         final Resources resources = getResources();
         mRootView = findViewById(R.id.photo_activity_root_view);
         mViewPager = (PhotoViewPager) findViewById(R.id.photo_view_pager);
@@ -609,4 +611,9 @@
     public void onCursorChanged(PhotoViewFragment fragment, Cursor cursor) {
         // do nothing
     }
+
+    @Override
+    public PhotoPagerAdapter getAdapter() {
+        return mAdapter;
+    }
 }
diff --git a/src/com/android/ex/photo/PhotoViewCallbacks.java b/src/com/android/ex/photo/PhotoViewCallbacks.java
index 075b116..6cb8a77 100644
--- a/src/com/android/ex/photo/PhotoViewCallbacks.java
+++ b/src/com/android/ex/photo/PhotoViewCallbacks.java
@@ -3,6 +3,7 @@
 import android.database.Cursor;
 import android.support.v4.app.Fragment;
 
+import com.android.ex.photo.adapters.PhotoPagerAdapter;
 import com.android.ex.photo.fragments.PhotoViewFragment;
 
 public interface PhotoViewCallbacks {
@@ -71,4 +72,9 @@
     public boolean isFragmentFullScreen(Fragment fragment);
 
     public void onCursorChanged(PhotoViewFragment fragment, Cursor cursor);
+
+    /**
+     * Returns the adapter associated with this activity.
+     */
+    public PhotoPagerAdapter getAdapter();
 }
diff --git a/src/com/android/ex/photo/adapters/PhotoPagerAdapter.java b/src/com/android/ex/photo/adapters/PhotoPagerAdapter.java
index 121ef46..56df485 100644
--- a/src/com/android/ex/photo/adapters/PhotoPagerAdapter.java
+++ b/src/com/android/ex/photo/adapters/PhotoPagerAdapter.java
@@ -35,7 +35,8 @@
     protected int mLoadingIndex;
     protected final float mMaxScale;
 
-    public PhotoPagerAdapter(Context context, android.support.v4.app.FragmentManager fm, Cursor c, float maxScale) {
+    public PhotoPagerAdapter(
+            Context context, android.support.v4.app.FragmentManager fm, Cursor c, float maxScale) {
         super(context, fm, c);
         mMaxScale = maxScale;
     }
@@ -63,7 +64,7 @@
             .setThumbnailUri(thumbnailUri)
             .setMaxInitialScale(mMaxScale);
 
-        return new PhotoViewFragment(builder.build(), position, this, onlyShowSpinner);
+        return PhotoViewFragment.newInstance(builder.build(), position, onlyShowSpinner);
     }
 
     @Override
diff --git a/src/com/android/ex/photo/fragments/PhotoViewFragment.java b/src/com/android/ex/photo/fragments/PhotoViewFragment.java
index bfa8a3c..afd40ba 100644
--- a/src/com/android/ex/photo/fragments/PhotoViewFragment.java
+++ b/src/com/android/ex/photo/fragments/PhotoViewFragment.java
@@ -17,7 +17,6 @@
 
 package com.android.ex.photo.fragments;
 
-import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
@@ -51,7 +50,10 @@
  * Displays a photo.
  */
 public class PhotoViewFragment extends Fragment implements
-        LoaderManager.LoaderCallbacks<Bitmap>, OnClickListener, OnScreenListener, CursorChangedListener {
+        LoaderManager.LoaderCallbacks<Bitmap>,
+        OnClickListener,
+        OnScreenListener,
+        CursorChangedListener {
     /**
      * Interface for components that are internally scrollable left-to-right.
      */
@@ -79,6 +81,10 @@
     protected final static String STATE_INTENT_KEY =
             "com.android.mail.photo.fragments.PhotoViewFragment.INTENT";
 
+    private final static String ARG_INTENT = "arg-intent";
+    private final static String ARG_POSITION = "arg-position";
+    private final static String ARG_SHOW_SPINNER = "arg-show-spinner";
+
     // Loader IDs
     protected final static int LOADER_ID_PHOTO = 1;
     protected final static int LOADER_ID_THUMBNAIL = 2;
@@ -100,64 +106,56 @@
     protected ImageView mRetryButton;
     protected ProgressBarWrapper mPhotoProgressBar;
 
-    protected final int mPosition;
+    protected int mPosition;
 
     /** Whether or not the fragment should make the photo full-screen */
     protected boolean mFullScreen;
 
     /** Whether or not this fragment will only show the loading spinner */
-    protected final boolean mOnlyShowSpinner;
+    protected boolean mOnlyShowSpinner;
 
     /** Whether or not the progress bar is showing valid information about the progress stated */
     protected boolean mProgressBarNeeded = true;
 
     protected View mPhotoPreviewAndProgress;
 
+    /** Public no-arg constructor for allowing the framework to handle orientation changes */
     public PhotoViewFragment() {
-        mPosition = -1;
-        mOnlyShowSpinner = false;
-        mProgressBarNeeded = true;
+        // Do nothing.
     }
 
-    public PhotoViewFragment(Intent intent, int position, PhotoPagerAdapter adapter,
-            boolean onlyShowSpinner) {
-        mIntent = intent;
-        mPosition = position;
-        mAdapter = adapter;
-        mOnlyShowSpinner = onlyShowSpinner;
-        mProgressBarNeeded = true;
+    /**
+     * Create a {@link PhotoViewFragment}.
+     * @param intent
+     * @param position
+     * @param onlyShowSpinner
+     * @return
+     */
+    public static final PhotoViewFragment newInstance(
+            Intent intent, int position, boolean onlyShowSpinner) {
+        final Bundle b = new Bundle();
+        b.putParcelable(ARG_INTENT, intent);
+        b.putInt(ARG_POSITION, position);
+        b.putBoolean(ARG_SHOW_SPINNER, onlyShowSpinner);
+        final PhotoViewFragment f = new PhotoViewFragment();
+        f.setArguments(b);
+        return f;
     }
 
     @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        mCallback = (PhotoViewCallbacks) activity;
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mCallback = (PhotoViewCallbacks) getActivity();
         if (mCallback == null) {
             throw new IllegalArgumentException(
                     "Activity must be a derived class of PhotoViewActivity");
         }
-
-        if (sPhotoSize == null) {
-            final DisplayMetrics metrics = new DisplayMetrics();
-            final WindowManager wm =
-                    (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
-            final ImageUtils.ImageSize imageSize = ImageUtils.sUseImageSize;
-            wm.getDefaultDisplay().getMetrics(metrics);
-            switch (imageSize) {
-                case EXTRA_SMALL: {
-                    // Use a photo that's 80% of the "small" size
-                    sPhotoSize = (Math.min(metrics.heightPixels, metrics.widthPixels) * 800) / 1000;
-                    break;
-                }
-
-                case SMALL:
-                case NORMAL:
-                default: {
-                    sPhotoSize = Math.min(metrics.heightPixels, metrics.widthPixels);
-                    break;
-                }
-            }
+        mAdapter = mCallback.getAdapter();
+        if (mAdapter == null) {
+            throw new IllegalStateException("Callback reported null adapter");
         }
+        // Don't call until we've setup the entire view
+        setViewVisibility();
     }
 
     @Override
@@ -169,6 +167,35 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        if (sPhotoSize == null) {
+            final DisplayMetrics metrics = new DisplayMetrics();
+            final WindowManager wm =
+                    (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
+            final ImageUtils.ImageSize imageSize = ImageUtils.sUseImageSize;
+            wm.getDefaultDisplay().getMetrics(metrics);
+            switch (imageSize) {
+                case EXTRA_SMALL:
+                    // Use a photo that's 80% of the "small" size
+                    sPhotoSize = (Math.min(metrics.heightPixels, metrics.widthPixels) * 800) / 1000;
+                    break;
+                case SMALL:
+                    // Fall through.
+                case NORMAL:
+                    // Fall through.
+                default:
+                    sPhotoSize = Math.min(metrics.heightPixels, metrics.widthPixels);
+                    break;
+            }
+        }
+
+        final Bundle bundle = getArguments();
+        if (bundle == null) {
+            return;
+        }
+        mIntent = bundle.getParcelable(ARG_INTENT);
+        mPosition = bundle.getInt(ARG_POSITION);
+        mOnlyShowSpinner = bundle.getBoolean(ARG_SHOW_SPINNER);
+        mProgressBarNeeded = true;
 
         if (savedInstanceState != null) {
             final Bundle state = savedInstanceState.getBundle(STATE_INTENT_KEY);
@@ -207,9 +234,6 @@
         mPhotoProgressBar = new ProgressBarWrapper(determinate, indeterminate, true);
         mEmptyText = (TextView) view.findViewById(R.id.empty_text);
         mRetryButton = (ImageView) view.findViewById(R.id.retry_button);
-
-        // Don't call until we've setup the entire view
-        setViewVisibility();
     }
 
     @Override
@@ -418,10 +442,8 @@
      * Sets view visibility depending upon whether or not we're in "full screen" mode.
      */
     private void setViewVisibility() {
-        final boolean fullScreen = mCallback.isFragmentFullScreen(this);
-        final boolean hide = fullScreen;
-
-        setFullScreen(hide);
+        final boolean fullScreen = mCallback == null ? false : mCallback.isFragmentFullScreen(this);
+        setFullScreen(fullScreen);
     }
 
     /**
@@ -433,6 +455,12 @@
 
     @Override
     public void onCursorChanged(Cursor cursor) {
+        if (mAdapter == null) {
+            // The adapter is set in onAttach(), and is guaranteed to be non-null. We have magically
+            // received an onCursorChanged without attaching to an activity. Ignore this cursor
+            // change.
+            return;
+        }
         if (cursor.moveToPosition(mPosition) && !isPhotoBound()) {
             mCallback.onCursorChanged(this, cursor);