Use new Loader API and properly unregister Observers

Change-Id: I0b50c1eb90b5ccfef36177c2c4392c523bcc96fb
diff --git a/src/com/android/contacts/views/ContactLoader.java b/src/com/android/contacts/views/ContactLoader.java
index 87c3a34..52046df 100644
--- a/src/com/android/contacts/views/ContactLoader.java
+++ b/src/com/android/contacts/views/ContactLoader.java
@@ -502,11 +502,13 @@
 
     @Override
     public void stopLoading() {
+        unregisterObserver();
         mContact = null;
     }
 
     @Override
     public void destroy() {
+        unregisterObserver();
         mContact = null;
         mDestroyed = true;
     }
diff --git a/src/com/android/contacts/views/detail/ContactDetailFragment.java b/src/com/android/contacts/views/detail/ContactDetailFragment.java
index 3802e77..73d0039 100644
--- a/src/com/android/contacts/views/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/views/detail/ContactDetailFragment.java
@@ -34,7 +34,9 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.app.LoaderManagingFragment;
+import android.app.Fragment;
+import android.app.LoaderManager;
+import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ActivityNotFoundException;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -91,12 +93,10 @@
 
 import java.util.ArrayList;
 
-public class ContactDetailFragment extends LoaderManagingFragment<ContactLoader.Result>
+public class ContactDetailFragment extends Fragment
         implements OnCreateContextMenuListener, OnItemClickListener {
     private static final String TAG = "ContactDetailFragment";
 
-    private static final String KEY_LOOKUP_URI = "lookupUri";
-
     private static final int MENU_ITEM_MAKE_DEFAULT = 3;
 
     private static final int LOADER_DETAILS = 1;
@@ -105,8 +105,6 @@
     private Uri mLookupUri;
     private Listener mListener;
 
-    private boolean mIsInitialized;
-
     private ContactLoader.Result mContactData;
     private ContactDetailHeaderView mHeaderView;
     private ListView mListView;
@@ -166,24 +164,6 @@
     }
 
     @Override
-    public void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-
-        if (savedState != null) {
-            mLookupUri = savedState.getParcelable(KEY_LOOKUP_URI);
-            if (mLookupUri != null) {
-                loadUri(mLookupUri);
-            }
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putParcelable(KEY_LOOKUP_URI, mLookupUri);
-    }
-
-    @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
         final View view = inflater.inflate(R.layout.contact_detail_fragment, container, false);
 
@@ -218,49 +198,17 @@
         return mLookupUri;
     }
 
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        getLoaderManager().initLoader(LOADER_DETAILS, null, mDetailLoaderListener);
+    }
+
     public void loadUri(Uri lookupUri) {
-        // TODO: Ensure we are not loading twice here
         mLookupUri = lookupUri;
-        if (mIsInitialized) startLoading(LOADER_DETAILS, null);
-    }
-
-    @Override
-    protected void onInitializeLoaders() {
-        mIsInitialized = true;
-        if (mLookupUri != null) startLoading(LOADER_DETAILS, null);
-    }
-
-    @Override
-    protected Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
-        switch (id) {
-            case LOADER_DETAILS: {
-                return new ContactLoader(mContext, mLookupUri);
-            }
-            default: {
-                Log.wtf(TAG, "Unknown ID in onCreateLoader: " + id);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    protected void onLoadFinished(Loader<ContactLoader.Result> loader,
-            ContactLoader.Result data) {
-        final int id = loader.getId();
-        switch (id) {
-            case LOADER_DETAILS:
-                if (data == ContactLoader.Result.NOT_FOUND) {
-                    // Item has been deleted
-                    Log.i(TAG, "No contact found. Closing activity");
-                    mListener.onContactNotFound();
-                    return;
-                }
-                mContactData = data;
-                bindData();
-                break;
-            default: {
-                Log.wtf(TAG, "Unknown ID in onLoadFinished: " + id);
-            }
+        if (getActivity() != null) {
+            getLoaderManager().restartLoader(LOADER_DETAILS, null, mDetailLoaderListener);
         }
     }
 
@@ -1055,6 +1003,29 @@
         return false;
     }
 
+    /**
+     * The listener for the detail loader
+     */
+    private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDetailLoaderListener =
+            new LoaderCallbacks<ContactLoader.Result>() {
+        @Override
+        public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
+            return new ContactLoader(mContext, mLookupUri);
+        }
+
+        @Override
+        public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
+            if (data == ContactLoader.Result.NOT_FOUND) {
+                // Item has been deleted
+                Log.i(TAG, "No contact found. Closing activity");
+                mListener.onContactNotFound();
+                return;
+            }
+            mContactData = data;
+            bindData();
+        }
+    };
+
     private ContactDetailHeaderView.Listener mHeaderViewListener =
             new ContactDetailHeaderView.Listener() {
         @Override
diff --git a/src/com/android/contacts/views/editor/ContactEditorFragment.java b/src/com/android/contacts/views/editor/ContactEditorFragment.java
index bbfa879..3b32384 100644
--- a/src/com/android/contacts/views/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/views/editor/ContactEditorFragment.java
@@ -39,7 +39,9 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.app.LoaderManagingFragment;
+import android.app.Fragment;
+import android.app.LoaderManager;
+import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ActivityNotFoundException;
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
@@ -90,7 +92,7 @@
 import java.util.Comparator;
 import java.util.Date;
 
-public class ContactEditorFragment extends LoaderManagingFragment<ContactLoader.Result> {
+public class ContactEditorFragment extends Fragment {
 
     private static final String TAG = "ContactEditorFragment";
 
@@ -140,8 +142,6 @@
 
     private ViewIdGenerator mViewIdGenerator;
 
-    private boolean mIsInitialized;
-
     private long mLoaderStartTime;
 
     public ContactEditorFragment() {
@@ -164,42 +164,26 @@
         return view;
     }
 
-    // TODO: Think about splitting this. Doing INSERT via load is kinda weird
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        if (Intent.ACTION_EDIT.equals(mAction)) {
+            if (mListener != null) mListener.setTitleTo(R.string.editContact_title_edit);
+            getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener);
+        } else if (Intent.ACTION_INSERT.equals(mAction)) {
+            if (mListener != null) mListener.setTitleTo(R.string.editContact_title_insert);
+
+            doAddAction();
+        } else throw new IllegalArgumentException("Unknown Action String " + mAction +
+                ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT);
+    }
+
     public void load(String action, Uri uri, String mimeType, Bundle intentExtras) {
         mAction = action;
         mUri = uri;
         mMimeType = mimeType;
         mIntentExtras = intentExtras;
-
-        if (mIsInitialized) {
-            if (Intent.ACTION_EDIT.equals(mAction)) {
-                // Read initial state from database
-                if (mListener != null) mListener.setTitleTo(R.string.editContact_title_edit);
-                startLoading(LOADER_DATA, null);
-            } else if (Intent.ACTION_INSERT.equals(mAction)) {
-                if (mListener != null) mListener.setTitleTo(R.string.editContact_title_insert);
-
-                doAddAction();
-            } else throw new IllegalArgumentException("Unknown Action String " + mAction +
-                    ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT);
-        }
-    }
-
-    @Override
-    protected void onInitializeLoaders() {
-        mIsInitialized = true;
-        if (mUri != null) {
-            if (Intent.ACTION_EDIT.equals(mAction)) {
-                // Read initial state from database
-                if (mListener != null) mListener.setTitleTo(R.string.editContact_title_edit);
-                startLoading(LOADER_DATA, null);
-            } else if (Intent.ACTION_INSERT.equals(mAction)) {
-                if (mListener != null) mListener.setTitleTo(R.string.editContact_title_insert);
-
-                doAddAction();
-            } else throw new IllegalArgumentException("Unknown Action String " + mAction +
-                    ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT);
-        }
     }
 
     public void setListener(Listener value) {
@@ -236,30 +220,6 @@
         }
     }
 
-    @Override
-    protected Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
-        mLoaderStartTime = SystemClock.elapsedRealtime();
-        return new ContactLoader(mContext, mUri);
-    }
-
-    @Override
-    protected void onLoadFinished(Loader<ContactLoader.Result> loader,
-            ContactLoader.Result data) {
-        if (data == ContactLoader.Result.NOT_FOUND) {
-            // Item has been deleted
-            Log.i(TAG, "No contact found. Closing fragment");
-            if (mListener != null) mListener.closeBecauseContactNotFound();
-            return;
-        }
-        final long loaderCurrentTime = SystemClock.elapsedRealtime();
-        Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
-
-        final long setDataStartTime = SystemClock.elapsedRealtime();
-        setData(data);
-        final long setDataEndTime = SystemClock.elapsedRealtime();
-        Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime));
-    }
-
     public void setData(ContactLoader.Result data) {
         mState = EntityDeltaList.fromIterator(data.getEntities().iterator());
         // TODO: Merge in Intent parameters can only be done on the first load.
@@ -1364,4 +1324,33 @@
     public Uri getUri() {
         return mUri;
     }
+
+    /**
+     * The listener for the data loader
+     */
+    private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDataLoaderListener =
+            new LoaderCallbacks<ContactLoader.Result>() {
+        @Override
+        public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
+            mLoaderStartTime = SystemClock.elapsedRealtime();
+            return new ContactLoader(mContext, mUri);
+        }
+
+        @Override
+        public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
+            final long loaderCurrentTime = SystemClock.elapsedRealtime();
+            Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
+            if (data == ContactLoader.Result.NOT_FOUND) {
+                // Item has been deleted
+                Log.i(TAG, "No contact found. Closing activity");
+                if (mListener != null) mListener.closeBecauseContactNotFound();
+                return;
+            }
+
+            final long setDataStartTime = SystemClock.elapsedRealtime();
+            setData(data);
+            final long setDataEndTime = SystemClock.elapsedRealtime();
+            Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime));
+        }
+    };
 }