Use the CursorWithExtras pattern for the message list.
This will make the message list a lot snappier. We were using two different loaders for the message list; one is to load the meta information and the other to load the actual message list. Unify them using the CursorWithExtras pattern. Change-Id: I02957bbca1b1fb74ca6eca14ad2535dfdbf03a5a
This commit is contained in:
parent
d42b3222fb
commit
41878c2813
@ -21,7 +21,6 @@ import com.android.email.Email;
|
||||
import com.android.email.NotificationController;
|
||||
import com.android.email.R;
|
||||
import com.android.email.RefreshManager;
|
||||
import com.android.email.data.MailboxAccountLoader;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
@ -92,8 +91,7 @@ public class MessageListFragment extends ListFragment
|
||||
private static final String BUNDLE_KEY_SELECTED_MESSAGE_ID
|
||||
= "messageListFragment.state.listState.selected_message_id";
|
||||
|
||||
private static final int LOADER_ID_MAILBOX_LOADER = 1;
|
||||
private static final int LOADER_ID_MESSAGES_LOADER = 2;
|
||||
private static final int LOADER_ID_MESSAGES_LOADER = 1;
|
||||
|
||||
/** Argument name(s) */
|
||||
private static final String ARG_ACCOUNT_ID = "accountId";
|
||||
@ -1149,48 +1147,7 @@ public class MessageListFragment extends ListFragment
|
||||
|
||||
// Start loading...
|
||||
final LoaderManager lm = getLoaderManager();
|
||||
lm.initLoader(LOADER_ID_MAILBOX_LOADER, null, new MailboxAccountLoaderCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loader callbacks for {@link MailboxAccountLoader}.
|
||||
*/
|
||||
private class MailboxAccountLoaderCallback implements LoaderManager.LoaderCallbacks<
|
||||
MailboxAccountLoader.Result> {
|
||||
@Override
|
||||
public Loader<MailboxAccountLoader.Result> onCreateLoader(int id, Bundle args) {
|
||||
final long mailboxId = getMailboxId();
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, MessageListFragment.this
|
||||
+ " onCreateLoader(mailbox) mailboxId=" + mailboxId);
|
||||
}
|
||||
return new MailboxAccountLoader(getActivity().getApplicationContext(), mailboxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<MailboxAccountLoader.Result> loader,
|
||||
MailboxAccountLoader.Result result) {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, MessageListFragment.this
|
||||
+ " onLoadFinished(mailbox) mailboxId=" + getMailboxId());
|
||||
}
|
||||
if (!result.mIsFound) {
|
||||
mCallback.onMailboxNotFound();
|
||||
return;
|
||||
}
|
||||
|
||||
mAccount = result.mAccount;
|
||||
mMailbox = result.mMailbox;
|
||||
mIsEasAccount = result.mIsEasAccount;
|
||||
mIsRefreshable = result.mIsRefreshable;
|
||||
mCountTotalAccounts = result.mCountTotalAccounts;
|
||||
getLoaderManager().initLoader(LOADER_ID_MESSAGES_LOADER, null,
|
||||
new MessagesLoaderCallback());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<MailboxAccountLoader.Result> loader) {
|
||||
}
|
||||
lm.initLoader(LOADER_ID_MESSAGES_LOADER, null, new MessagesLoaderCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1211,11 +1168,25 @@ public class MessageListFragment extends ListFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, MessageListFragment.this
|
||||
+ " onLoadFinished(messages) mailboxId=" + getMailboxId());
|
||||
}
|
||||
MessagesAdapter.CursorWithExtras cursor =
|
||||
(MessagesAdapter.CursorWithExtras) c;
|
||||
|
||||
if (!cursor.mIsFound) {
|
||||
mCallback.onMailboxNotFound();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the "extras" part.
|
||||
mAccount = cursor.mAccount;
|
||||
mMailbox = cursor.mMailbox;
|
||||
mIsEasAccount = cursor.mIsEasAccount;
|
||||
mIsRefreshable = cursor.mIsRefreshable;
|
||||
mCountTotalAccounts = cursor.mCountTotalAccounts;
|
||||
|
||||
// Suspend message notifications as long as we're resumed
|
||||
adjustMessageNotification(false);
|
||||
|
@ -21,6 +21,7 @@ import com.android.email.ResourceHelper;
|
||||
import com.android.email.data.ThrottlingCursorLoader;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.provider.EmailContent;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
import com.android.emailcommon.provider.EmailContent.MessageColumns;
|
||||
import com.android.emailcommon.provider.Mailbox;
|
||||
@ -30,6 +31,7 @@ import com.android.emailcommon.utility.Utility;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWrapper;
|
||||
import android.database.MatrixCursor;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
@ -93,6 +95,36 @@ import java.util.Set;
|
||||
|
||||
private final Callback mCallback;
|
||||
|
||||
/**
|
||||
* The actual return type from the loader.
|
||||
*/
|
||||
public static class CursorWithExtras extends CursorWrapper {
|
||||
/** Whether the mailbox is found. */
|
||||
public final boolean mIsFound;
|
||||
/** {@link Account} that owns the mailbox. Null for combined mailboxes. */
|
||||
public final Account mAccount;
|
||||
/** {@link Mailbox} for the loaded mailbox. Null for combined mailboxes. */
|
||||
public final Mailbox mMailbox;
|
||||
/** {@code true} if the account is an EAS account */
|
||||
public final boolean mIsEasAccount;
|
||||
/** {@code true} if the loaded mailbox can be refreshed. */
|
||||
public final boolean mIsRefreshable;
|
||||
/** the number of accounts currently configured. */
|
||||
public final int mCountTotalAccounts;
|
||||
|
||||
private CursorWithExtras(Cursor cursor,
|
||||
boolean found, Account account, Mailbox mailbox, boolean isEasAccount,
|
||||
boolean isRefreshable, int countTotalAccounts) {
|
||||
super(cursor);
|
||||
mIsFound = found;
|
||||
mAccount = account;
|
||||
mMailbox = mailbox;
|
||||
mIsEasAccount = isEasAccount;
|
||||
mIsRefreshable = isRefreshable;
|
||||
mCountTotalAccounts = countTotalAccounts;
|
||||
}
|
||||
}
|
||||
|
||||
public MessagesAdapter(Context context, Callback callback) {
|
||||
super(context.getApplicationContext(), null, 0 /* no auto requery */);
|
||||
mResourceHelper = ResourceHelper.getInstance(context);
|
||||
@ -222,6 +254,11 @@ import java.util.Set;
|
||||
view.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the loader for {@link MessageListFragment}.
|
||||
*
|
||||
* @return always of {@link CursorWithExtras}.
|
||||
*/
|
||||
public static Loader<Cursor> createLoader(Context context, long mailboxId) {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MessagesAdapter createLoader mailboxId=" + mailboxId);
|
||||
@ -266,7 +303,35 @@ import java.util.Set;
|
||||
// return an empty cursor
|
||||
returnCursor = new MatrixCursor(getProjection());
|
||||
}
|
||||
return Utility.CloseTraceCursorWrapper.get(returnCursor);
|
||||
return loadExtras(returnCursor);
|
||||
}
|
||||
|
||||
private Cursor loadExtras(Cursor baseCursor) {
|
||||
boolean found = false;
|
||||
Account account = null;
|
||||
Mailbox mailbox = null;
|
||||
boolean isEasAccount = false;
|
||||
boolean isRefreshable = false;
|
||||
|
||||
if (mMailboxId < 0) {
|
||||
// Magic mailbox.
|
||||
found = true;
|
||||
} else {
|
||||
mailbox = Mailbox.restoreMailboxWithId(mContext, mMailboxId);
|
||||
if (mailbox != null) {
|
||||
account = Account.restoreAccountWithId(mContext, mailbox.mAccountKey);
|
||||
if (account != null) {
|
||||
found = true;
|
||||
isEasAccount = account.isEasAccount(mContext) ;
|
||||
isRefreshable = Mailbox.isRefreshable(mContext, mMailboxId);
|
||||
} else { // Account removed?
|
||||
mailbox = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
final int countAccounts = EmailContent.count(mContext, Account.CONTENT_URI);
|
||||
return new CursorWithExtras(baseCursor, found, account, mailbox, isEasAccount,
|
||||
isRefreshable, countAccounts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.email.data;
|
||||
|
||||
import com.android.emailcommon.provider.EmailContent;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.Mailbox;
|
||||
|
||||
import android.content.AsyncTaskLoader;
|
||||
import android.content.Context;
|
||||
|
||||
|
||||
/**
|
||||
* Loader to load {@link Mailbox} and {@link Account}.
|
||||
*/
|
||||
public class MailboxAccountLoader extends AsyncTaskLoader<MailboxAccountLoader.Result> {
|
||||
public static class Result {
|
||||
public final boolean mIsFound;
|
||||
public final Account mAccount;
|
||||
public final Mailbox mMailbox;
|
||||
public final boolean mIsEasAccount;
|
||||
public final boolean mIsRefreshable;
|
||||
public final int mCountTotalAccounts;
|
||||
|
||||
private Result(boolean found, Account account, Mailbox mailbox, boolean isEasAccount,
|
||||
boolean isRefreshable, int countTotalAccounts) {
|
||||
mIsFound = found;
|
||||
mAccount = account;
|
||||
mMailbox = mailbox;
|
||||
mIsEasAccount = isEasAccount;
|
||||
mIsRefreshable = isRefreshable;
|
||||
mCountTotalAccounts = countTotalAccounts;
|
||||
}
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final long mMailboxId;
|
||||
|
||||
public MailboxAccountLoader(Context context, long mailboxId) {
|
||||
super(context);
|
||||
if (mailboxId == -1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
mContext = context;
|
||||
mMailboxId = mailboxId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result loadInBackground() {
|
||||
boolean found = false;
|
||||
Account account = null;
|
||||
Mailbox mailbox = null;
|
||||
boolean isEasAccount = false;
|
||||
boolean isRefreshable = false;
|
||||
|
||||
if (mMailboxId < 0) {
|
||||
// Magic mailbox.
|
||||
found = true;
|
||||
} else {
|
||||
mailbox = Mailbox.restoreMailboxWithId(mContext, mMailboxId);
|
||||
if (mailbox != null) {
|
||||
account = Account.restoreAccountWithId(mContext, mailbox.mAccountKey);
|
||||
if (account != null) {
|
||||
found = true;
|
||||
isEasAccount = account.isEasAccount(mContext) ;
|
||||
isRefreshable = Mailbox.isRefreshable(mContext, mMailboxId);
|
||||
} else { // Account removed?
|
||||
mailbox = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
final int countAccounts = EmailContent.count(mContext, Account.CONTENT_URI);
|
||||
Result result = new Result(found, account, mailbox, isEasAccount, isRefreshable,
|
||||
countAccounts);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
cancelLoad();
|
||||
forceLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
stopLoading();
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.email.data;
|
||||
package com.android.email.activity;
|
||||
|
||||
import com.android.email.DBTestHelper;
|
||||
import com.android.email.provider.ProviderTestUtils;
|
||||
@ -24,7 +24,13 @@ import com.android.emailcommon.provider.Mailbox;
|
||||
import android.content.Context;
|
||||
import android.test.LoaderTestCase;
|
||||
|
||||
public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
public class MessagesAdapterTests extends LoaderTestCase {
|
||||
// Account ID that's probably not in the database.
|
||||
private static final long NO_SUCH_ACCOUNT_ID = 1234567890123L;
|
||||
|
||||
// Mailbox ID that's probably not in the database.
|
||||
private static final long NO_SUCH_MAILBOX_ID = 1234567890123L;
|
||||
|
||||
// Isolated Context for providers.
|
||||
private Context mProviderContext;
|
||||
|
||||
@ -50,6 +56,11 @@ public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
return box.mId;
|
||||
}
|
||||
|
||||
private MessagesAdapter.CursorWithExtras getLoaderResult(long mailboxId) {
|
||||
return (MessagesAdapter.CursorWithExtras) getLoaderResultSynchronously(
|
||||
MessagesAdapter.createLoader(mProviderContext, mailboxId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for normal case. (account, mailbox found)
|
||||
*/
|
||||
@ -57,8 +68,7 @@ public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
final long accountId = createAccount(false);
|
||||
final long mailboxId = createMailbox(accountId, Mailbox.TYPE_MAIL);
|
||||
|
||||
MailboxAccountLoader.Result result = getLoaderResultSynchronously(
|
||||
new MailboxAccountLoader(mProviderContext, mailboxId));
|
||||
MessagesAdapter.CursorWithExtras result = getLoaderResult(mailboxId);
|
||||
assertTrue(result.mIsFound);
|
||||
assertEquals(accountId, result.mAccount.mId);
|
||||
assertEquals(mailboxId, result.mMailbox.mId);
|
||||
@ -73,8 +83,7 @@ public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
final long accountId = createAccount(true);
|
||||
final long mailboxId = createMailbox(accountId, Mailbox.TYPE_MAIL);
|
||||
|
||||
MailboxAccountLoader.Result result = getLoaderResultSynchronously(
|
||||
new MailboxAccountLoader(mProviderContext, mailboxId));
|
||||
MessagesAdapter.CursorWithExtras result = getLoaderResult(mailboxId);
|
||||
assertTrue(result.mIsFound);
|
||||
assertEquals(accountId, result.mAccount.mId);
|
||||
assertEquals(mailboxId, result.mMailbox.mId);
|
||||
@ -89,8 +98,7 @@ public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
final long accountId = createAccount(false);
|
||||
final long mailboxId = createMailbox(accountId, Mailbox.TYPE_DRAFTS);
|
||||
|
||||
MailboxAccountLoader.Result result = getLoaderResultSynchronously(
|
||||
new MailboxAccountLoader(mProviderContext, mailboxId));
|
||||
MessagesAdapter.CursorWithExtras result = getLoaderResult(mailboxId);
|
||||
assertTrue(result.mIsFound);
|
||||
assertEquals(accountId, result.mAccount.mId);
|
||||
assertEquals(mailboxId, result.mMailbox.mId);
|
||||
@ -102,8 +110,7 @@ public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
* Mailbox not found.
|
||||
*/
|
||||
public void testMailboxNotFound() {
|
||||
MailboxAccountLoader.Result result = getLoaderResultSynchronously(
|
||||
new MailboxAccountLoader(mProviderContext, 123));
|
||||
MessagesAdapter.CursorWithExtras result = getLoaderResult(NO_SUCH_MAILBOX_ID);
|
||||
assertFalse(result.mIsFound);
|
||||
assertNull(result.mAccount);
|
||||
assertNull(result.mMailbox);
|
||||
@ -115,10 +122,9 @@ public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
* Account not found.
|
||||
*/
|
||||
public void testAccountNotFound() {
|
||||
final long mailboxId = createMailbox(1, Mailbox.TYPE_MAIL);
|
||||
final long mailboxId = createMailbox(NO_SUCH_ACCOUNT_ID, Mailbox.TYPE_MAIL);
|
||||
|
||||
MailboxAccountLoader.Result result = getLoaderResultSynchronously(
|
||||
new MailboxAccountLoader(mProviderContext, mailboxId));
|
||||
MessagesAdapter.CursorWithExtras result = getLoaderResult(mailboxId);
|
||||
assertFalse(result.mIsFound);
|
||||
assertNull(result.mAccount);
|
||||
assertNull(result.mMailbox);
|
||||
@ -130,8 +136,7 @@ public class MailboxAccountLoaderTestCase extends LoaderTestCase {
|
||||
* Magic mailbox. (always found)
|
||||
*/
|
||||
public void testMagicMailbox() {
|
||||
MailboxAccountLoader.Result result = getLoaderResultSynchronously(
|
||||
new MailboxAccountLoader(mProviderContext, Mailbox.QUERY_ALL_INBOXES));
|
||||
MessagesAdapter.CursorWithExtras result = getLoaderResult(Mailbox.QUERY_ALL_INBOXES);
|
||||
assertTrue(result.mIsFound);
|
||||
assertNull(result.mAccount);
|
||||
assertNull(result.mMailbox);
|
Loading…
Reference in New Issue
Block a user