Add convenience methods for account loading

Test: ran GoogleContactsTests

Bug 33627801

Change-Id: Ib673838d9b041e5dc512a94bfaf47b4caf4a540f
diff --git a/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java b/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
index 3531125..2ca51f6 100644
--- a/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
@@ -36,6 +36,7 @@
 import com.android.contacts.editor.ContactEditorUtils;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.account.AccountInfo;
+import com.android.contacts.model.account.AccountType;
 import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.model.account.AccountsLoader;
 import com.android.contacts.util.AccountsListAdapter;
@@ -54,7 +55,7 @@
  * account for this contact.
  */
 public class ContactEditorAccountsChangedActivity extends Activity
-        implements LoaderManager.LoaderCallbacks<List<AccountInfo>> {
+        implements AccountsLoader.AccountsListener {
 
     private static final String TAG = ContactEditorAccountsChangedActivity.class.getSimpleName();
 
@@ -102,7 +103,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mEditorUtils = ContactEditorUtils.create(this);
-        getLoaderManager().initLoader(0, null, this);
+        AccountsLoader.loadAccounts(this, 0, AccountTypeManager.writableFilter());
     }
 
     @Override
@@ -236,16 +237,7 @@
     }
 
     @Override
-    public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
-        return new AccountsLoader(this, AccountTypeManager.writableFilter());
-    }
-
-    @Override
-    public void onLoadFinished(Loader<List<AccountInfo>> loader, List<AccountInfo> data) {
-        updateDisplayedAccounts(data);
-    }
-
-    @Override
-    public void onLoaderReset(Loader<List<AccountInfo>> loader) {
+    public void onAccountsLoaded(List<AccountInfo> accounts) {
+        updateDisplayedAccounts(accounts);
     }
 }
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index ede4a37..489cfd1 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -111,7 +111,8 @@
         JoinContactConfirmationDialogFragment.Listener,
         AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
         CancelEditDialogFragment.Listener,
-        RawContactEditorView.Listener, PhotoEditorView.Listener {
+        RawContactEditorView.Listener, PhotoEditorView.Listener,
+        AccountsLoader.AccountsListener {
 
     static final String TAG = "ContactEditor";
 
@@ -435,52 +436,6 @@
                 }
             };
 
-    protected LoaderManager.LoaderCallbacks<List<AccountInfo>> mAccountsLoaderListener =
-            new LoaderManager.LoaderCallbacks<List<AccountInfo>>() {
-                @Override
-                public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
-                    return new AccountsLoader(getActivity(), AccountTypeManager.writableFilter());
-                }
-
-                @Override
-                public void onLoadFinished(
-                        Loader<List<AccountInfo>> loader, List<AccountInfo> data) {
-                    mWritableAccounts = data;
-                    // The user may need to select a new account to save to
-                    if (mAccountWithDataSet == null && mHasNewContact) {
-                        selectAccountAndCreateContact();
-                    }
-
-                    final RawContactEditorView view = getContent();
-                    if (view == null) {
-                        return;
-                    }
-                    view.setAccounts(data);
-                    if (mAccountWithDataSet == null && view.getCurrentRawContactDelta() == null) {
-                        return;
-                    }
-
-                    final AccountWithDataSet account = mAccountWithDataSet != null
-                            ? mAccountWithDataSet
-                            : view.getCurrentRawContactDelta().getAccountWithDataSet();
-
-                    // The current account was removed
-                    if (!AccountInfo.contains(data, account) && !data.isEmpty()) {
-                        if (isReadyToBindEditors()) {
-                            onRebindEditorsForNewContact(getContent().getCurrentRawContactDelta(),
-                                    account, data.get(0).getAccount());
-                        } else {
-                            mAccountWithDataSet = data.get(0).getAccount();
-                        }
-                    }
-                }
-
-                @Override
-                public void onLoaderReset(Loader<List<AccountInfo>> loader) {
-                }
-            };
-
-
     private long mPhotoRawContactId;
     private Bundle mUpdatedPhotos = new Bundle();
 
@@ -611,7 +566,7 @@
         }
 
         if (mHasNewContact) {
-            getLoaderManager().initLoader(LOADER_ACCOUNTS, null, mAccountsLoaderListener);
+            AccountsLoader.loadAccounts(this, LOADER_ACCOUNTS, AccountTypeManager.writableFilter());
         }
     }
 
@@ -720,6 +675,38 @@
         }
     }
 
+    @Override
+    public void onAccountsLoaded(List<AccountInfo> data) {
+        mWritableAccounts = data;
+        // The user may need to select a new account to save to
+        if (mAccountWithDataSet == null && mHasNewContact) {
+            selectAccountAndCreateContact();
+        }
+
+        final RawContactEditorView view = getContent();
+        if (view == null) {
+            return;
+        }
+        view.setAccounts(data);
+        if (mAccountWithDataSet == null && view.getCurrentRawContactDelta() == null) {
+            return;
+        }
+
+        final AccountWithDataSet account = mAccountWithDataSet != null
+                ? mAccountWithDataSet
+                : view.getCurrentRawContactDelta().getAccountWithDataSet();
+
+        // The current account was removed
+        if (!AccountInfo.contains(data, account) && !data.isEmpty()) {
+            if (isReadyToBindEditors()) {
+                onRebindEditorsForNewContact(getContent().getCurrentRawContactDelta(),
+                        account, data.get(0).getAccount());
+            } else {
+                mAccountWithDataSet = data.get(0).getAccount();
+            }
+        }
+    }
+
     //
     // Options menu
     //
diff --git a/src/com/android/contacts/model/account/AccountsLoader.java b/src/com/android/contacts/model/account/AccountsLoader.java
index 78f309b..260c44b 100644
--- a/src/com/android/contacts/model/account/AccountsLoader.java
+++ b/src/com/android/contacts/model/account/AccountsLoader.java
@@ -15,8 +15,13 @@
  */
 package com.android.contacts.model.account;
 
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.LoaderManager;
 import android.content.Context;
 import android.content.IntentFilter;
+import android.content.Loader;
+import android.os.Bundle;
 
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.util.concurrent.ListenableFutureLoader;
@@ -55,4 +60,47 @@
                 AccountInfo.extractAccounts(next));
     }
 
+
+    public interface AccountsListener {
+        void onAccountsLoaded(List<AccountInfo> accounts);
+    }
+
+    /**
+     * Loads the accounts into the target fragment using {@link LoaderManager}
+     *
+     * <p>This is a convenience method to reduce the
+     * boilerplate needed when implementing {@link android.app.LoaderManager.LoaderCallbacks}
+     * in the simple case that the fragment wants to just load the accounts directly</p>
+     */
+    public static <FragmentType extends Fragment & AccountsListener> void loadAccounts(
+            final FragmentType fragment, int loaderId, final Predicate<AccountInfo> filter) {
+        loadAccounts(
+                fragment.getActivity(), fragment.getLoaderManager(), loaderId, filter, fragment);
+    }
+
+    public static <ActivityType extends Activity & AccountsListener> void loadAccounts(
+            final ActivityType activity, int id, final Predicate<AccountInfo> filter) {
+        loadAccounts(activity, activity.getLoaderManager(), id, filter, activity);
+    }
+
+    private static void loadAccounts(final Context context, LoaderManager loaderManager, int id,
+            final Predicate<AccountInfo> filter, final AccountsListener listener) {
+        loaderManager.initLoader(id, null,
+                new LoaderManager.LoaderCallbacks<List<AccountInfo>>() {
+                    @Override
+                    public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
+                        return new AccountsLoader(context, filter);
+                    }
+
+                    @Override
+                    public void onLoadFinished(
+                            Loader<List<AccountInfo>> loader, List<AccountInfo> data) {
+                        listener.onAccountsLoaded(data);
+                    }
+
+                    @Override
+                    public void onLoaderReset(Loader<List<AccountInfo>> loader) {
+                    }
+                });
+    }
 }
diff --git a/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java b/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
index 7cc307f..a9ec250 100644
--- a/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
+++ b/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
@@ -55,8 +55,6 @@
 import com.android.contacts.logging.ScreenEvent.ScreenType;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.account.AccountInfo;
-import com.android.contacts.model.account.AccountType;
-import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.model.account.AccountsLoader;
 import com.android.contacts.util.AccountFilterUtil;
 import com.android.contacts.util.ImplicitIntentsUtil;
@@ -68,7 +66,7 @@
  * This fragment shows the preferences for "display options"
  */
 public class DisplayOptionsPreferenceFragment extends PreferenceFragment
-        implements Preference.OnPreferenceClickListener {
+        implements Preference.OnPreferenceClickListener, AccountsLoader.AccountsListener {
 
     private static final int REQUEST_CODE_CUSTOM_CONTACTS_FILTER = 0;
 
@@ -160,26 +158,6 @@
         }
     };
 
-    private final LoaderManager.LoaderCallbacks<List<AccountInfo>> mAccountsLoaderListener =
-            new LoaderManager.LoaderCallbacks<List<AccountInfo>>() {
-                @Override
-                public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
-                    return new AccountsLoader(getActivity(), AccountTypeManager.writableFilter());
-                }
-
-                @Override
-                public void onLoadFinished(
-                        Loader<List<AccountInfo>> loader, List<AccountInfo> data) {
-                    if (data.isEmpty()) {
-                        removeUnsupportedAccountPreferences();
-                    }
-                }
-
-                @Override
-                public void onLoaderReset(Loader<List<AccountInfo>> loader) {
-                }
-            };
-
     public static DisplayOptionsPreferenceFragment newInstance(String newLocalProfileExtra,
             boolean areContactsAvailable) {
         final DisplayOptionsPreferenceFragment fragment = new DisplayOptionsPreferenceFragment();
@@ -266,7 +244,7 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         getLoaderManager().initLoader(LOADER_PROFILE, null, mProfileLoaderListener);
-        getLoaderManager().initLoader(LOADER_ACCOUNTS, null, mAccountsLoaderListener);
+        AccountsLoader.loadAccounts(this, LOADER_ACCOUNTS, AccountTypeManager.writableFilter());
     }
 
     @Override
@@ -313,9 +291,13 @@
         }
     }
 
-    private void removeUnsupportedAccountPreferences() {
-        getPreferenceScreen().removePreference(findPreference(KEY_DEFAULT_ACCOUNT));
-        getPreferenceScreen().removePreference(findPreference(KEY_CUSTOM_CONTACTS_FILTER));
+    @Override
+    public void onAccountsLoaded(List<AccountInfo> accounts) {
+        // Hide accounts preferences if no writable accounts exist
+        if (accounts.isEmpty()) {
+            getPreferenceScreen().removePreference(findPreference(KEY_DEFAULT_ACCOUNT));
+            getPreferenceScreen().removePreference(findPreference(KEY_CUSTOM_CONTACTS_FILTER));
+        }
     }
 
     @Override