Merge "Remove clearContent and other stuff for reusing fragments"

This commit is contained in:
Makoto Onuki 2011-05-05 10:08:41 -07:00 committed by Android (Google) Code Review
commit f456fa88bc
3 changed files with 35 additions and 193 deletions

View File

@ -21,6 +21,7 @@ import com.android.email.ControllerResultUiThreadWrapper;
import com.android.email.Email;
import com.android.email.MessagingExceptionStrings;
import com.android.email.R;
import com.android.email.RefreshManager;
import com.android.email.activity.setup.AccountSettingsXL;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.EmailContent.Account;
@ -226,7 +227,7 @@ public class MailboxList extends Activity implements MailboxListFragment.Callbac
private void onRefresh() {
Controller controller = Controller.getInstance(getApplication());
showProgressIcon(true);
mListFragment.onRefresh();
RefreshManager.getInstance(this).refreshMailboxList(mAccountId);
}
private void onAccounts() {

View File

@ -56,17 +56,7 @@ import java.util.Timer;
import java.util.TimerTask;
/**
* This fragment presents a list of mailboxes for a given account. The "API" includes the
* following elements which must be provided by the host Activity.
*
* - call bindActivityInfo() to provide the account ID and set callbacks
* - provide callbacks for onOpen and onRefresh
* - pass-through implementations of onCreateContextMenu() and onContextItemSelected() (temporary)
*
* TODO Restoring ListView state -- don't do this when changing accounts
* TODO Restoring scroll position on screen rotation is broken.
* TODO Remove clearContent -> most probably this is the cause for the scroll position not being
* restored issue.
* This fragment presents a list of mailboxes for a given account.
*/
public class MailboxListFragment extends ListFragment implements OnItemClickListener,
OnDragListener {
@ -119,14 +109,9 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
private static Integer sDropTrashColor;
private static Drawable sDropActiveDrawable;
private long mLastLoadedAccountId = -1;
private long mAccountId = -1;
private long mParentMailboxId = DEFAULT_MAILBOX_ID;
private long mSelectedMailboxId = -1;
/** The ID of the mailbox that we have been asked to load */
private long mLoadedMailboxId = -1;
private boolean mOpenRequested;
// True if a drag is currently in progress
private boolean mDragInProgress;
@ -281,31 +266,13 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
if (args != null) {
openMailboxes(args.getLong(ARG_ACCOUNT_ID), args.getLong(ARG_PARENT_MAILBOX_ID));
}
startLoading();
}
public void setCallback(Callback callback) {
mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
}
private void clearContent() {
getLoaderManager().destroyLoader(MAILBOX_LOADER_ID);
mLastLoadedAccountId = -1;
mAccountId = -1;
mParentMailboxId = DEFAULT_MAILBOX_ID;
mSelectedMailboxId = -1;
mLoadedMailboxId = -1;
mOpenRequested = false;
mDropTargetId = NO_DROP_TARGET;
mDropTargetView = null;
if (mListAdapter != null) {
mListAdapter.swapCursor(null);
}
setListShownNoAnimation(false);
}
/**
* Opens the top-level mailboxes for the given account ID. If the account is currently
* loaded, the list of top-level mailbox will not be reloaded unless <code>forceReload</code>
@ -328,16 +295,8 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
parentMailboxId = DEFAULT_MAILBOX_ID;
}
if ((mAccountId == accountId) && (mParentMailboxId == parentMailboxId)) {
return;
}
clearContent();
mOpenRequested = true;
mAccountId = accountId;
mParentMailboxId = parentMailboxId;
if (mResumed) {
startLoading();
}
}
/**
@ -388,10 +347,10 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
super.onResume();
mResumed = true;
// If we're recovering from the stopped state, we don't have to reload.
// (when mOpenRequested = false)
if (mAccountId != -1 && mOpenRequested) {
startLoading();
// Fetch the latest mailbox list from the server here if stale so that the user always
// sees the (reasonably) up-to-date mailbox list, without pressing "refresh".
if (mRefreshManager.isMailboxListStale(mAccountId)) {
mRefreshManager.refreshMailboxList(mAccountId);
}
}
@ -449,47 +408,25 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MailboxListFragment startLoading");
}
mOpenRequested = false;
// Clear the list. (ListFragment will show the "Loading" animation)
setListShown(false);
// If we've already loaded for a different account OR if we've loaded for a different
// mailbox, discard the previous result and load again.
boolean saveListState = true;
final LoaderManager lm = getLoaderManager();
long lastLoadedMailboxId = mLoadedMailboxId;
mLoadedMailboxId = mParentMailboxId;
if ((lastLoadedMailboxId != mParentMailboxId) ||
((mLastLoadedAccountId != -1) && (mLastLoadedAccountId != mAccountId))) {
lm.destroyLoader(MAILBOX_LOADER_ID);
saveListState = false;
refreshMailboxListIfStale();
}
/**
* Don't use {@link LoaderManager#restartLoader(int, Bundle, LoaderCallbacks)}, because
* we want to reuse the previous result if the Loader has been retained.
*/
lm.initLoader(MAILBOX_LOADER_ID, null,
new MailboxListLoaderCallbacks(saveListState, mLoadedMailboxId));
lm.initLoader(MAILBOX_LOADER_ID, null, new MailboxListLoaderCallbacks());
}
// TODO This class probably should be made static. There are many calls into the enclosing
// class and we need to be cautious about what we call while in these callbacks
private class MailboxListLoaderCallbacks implements LoaderCallbacks<Cursor> {
private boolean mSaveListState;
private final long mMailboxId;
public MailboxListLoaderCallbacks(boolean saveListState, long mailboxId) {
mSaveListState = saveListState;
mMailboxId = mailboxId;
}
private boolean mIsFirstLoad;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MailboxListFragment onCreateLoader");
}
return MailboxFragmentAdapter.createLoader(getActivity(), mAccountId, mMailboxId);
mIsFirstLoad = true;
return MailboxFragmentAdapter.createLoader(getActivity(), mAccountId, mParentMailboxId);
}
@Override
@ -497,17 +434,10 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MailboxListFragment onLoadFinished");
}
if (mMailboxId != mLoadedMailboxId) {
return;
}
mLastLoadedAccountId = mAccountId;
// Save list view state (primarily scroll position)
final ListView lv = getListView();
final Parcelable listState;
if (!mSaveListState) {
listState = null; // Don't preserve list state
} else if (mSavedListState != null) {
if (mSavedListState != null) {
listState = mSavedListState;
mSavedListState = null;
} else {
@ -525,9 +455,9 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
setListAdapter(mListAdapter);
setListShown(true);
// We want to make selection visible only when account is changing..
// i.e. Refresh caused by content changed events shouldn't scroll the list.
highlightSelectedMailbox(!mSaveListState);
// We want to make visible the selection only for the first load.
// Re-load caused by content changed events shouldn't scroll the list.
highlightSelectedMailbox(mIsFirstLoad);
}
// List has been reloaded; clear any drop target information
@ -539,15 +469,11 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
lv.onRestoreInstanceState(listState);
}
// Clear this for next reload triggered by content changed events.
mSaveListState = true;
mIsFirstLoad = false;
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
if (mMailboxId != mLoadedMailboxId) {
return;
}
mListAdapter.swapCursor(null);
}
}
@ -564,18 +490,6 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
}
}
public void onRefresh() {
if (mAccountId != -1) {
mRefreshManager.refreshMailboxList(mAccountId);
}
}
private void refreshMailboxListIfStale() {
if (mRefreshManager.isMailboxListStale(mAccountId)) {
mRefreshManager.refreshMailboxList(mAccountId);
}
}
/**
* Highlight the selected mailbox.
*/

View File

@ -30,6 +30,7 @@ import com.android.emailcommon.provider.EmailContent.Mailbox;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.emailcommon.utility.Utility;
import com.google.common.annotations.VisibleForTesting;
import android.app.Activity;
import android.app.ListFragment;
@ -48,7 +49,6 @@ import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextPaint;
import android.util.Log;
@ -75,7 +75,6 @@ import java.security.InvalidParameterException;
import java.util.HashSet;
import java.util.Set;
// TODO Better handling of restoring list position/adapter check status
/**
* Message list.
*
@ -86,13 +85,6 @@ import java.util.Set;
* </ul>
* We run them sequentially. i.e. First starts {@link MailboxAccountLoader}, and when it finishes
* starts the other.
*
* TODO Finalize batch move UI. Probably the "move" button should be disabled or hidden when
* the selection contains non-movable messages. But then how does the user know why they can't be
* moved?
* TODO Restoring scroll position on screen rotation is broken.
* TODO Restoring selected messages on screen rotation is broken.
* TODO Remove clearContent -> most probably this is the cause for the two issues above.
*/
public class MessageListFragment extends ListFragment
implements OnItemClickListener, OnItemLongClickListener, MessagesAdapter.Callback,
@ -130,7 +122,6 @@ public class MessageListFragment extends ListFragment
private MessagesAdapter mListAdapter;
private long mMailboxId = -1;
private long mLastLoadedMailboxId = -1;
private long mSelectedMessageId = -1;
private Account mAccount;
@ -369,8 +360,8 @@ public class MessageListFragment extends ListFragment
outState.putLong(BUNDLE_KEY_SELECTED_MESSAGE_ID, mSelectedMessageId);
}
// Unit tests use it
/* package */void restoreInstanceState(Bundle savedInstanceState) {
@VisibleForTesting
void restoreInstanceState(Bundle savedInstanceState) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MessageListFragment restoreInstanceState");
}
@ -416,29 +407,6 @@ public class MessageListFragment extends ListFragment
updateSelectionMode();
}
/**
* Clear all the content, stop the loaders, etc -- should be called when the fragment is hidden.
*/
private void clearContent() {
mMailboxId = -1;
mLastLoadedMailboxId = -1;
mSelectedMessageId = -1;
mAccount = null;
mMailbox = null;
mIsEasAccount = false;
mIsRefreshable = false;
mCountTotalAccounts = 0;
mOpenRequested = false;
mShowSendCommand = false;
stopLoaders();
onDeselectAll();
if (mListAdapter != null) {
mListAdapter.swapCursor(null);
}
setListShownNoAnimation(false);
}
/**
* Called by an Activity to open an mailbox.
*
@ -453,15 +421,14 @@ public class MessageListFragment extends ListFragment
if (mailboxId == -1) {
throw new InvalidParameterException();
}
if (mMailboxId == mailboxId) {
return;
}
clearContent();
mOpenRequested = true;
mMailboxId = mailboxId;
// STOPSHIP Clean it up once the phone activities are gone. (See MailboxListFragment)
// - Move startLoading() to onActivityCreated
// - Remove mOpenRequested
// - Remove the mOpenRequested check from onResume
// etc...
if (mResumed) {
startLoading();
}
@ -937,8 +904,6 @@ public class MessageListFragment extends ListFragment
}
}
refreshList();
return numChanged;
}
@ -1106,22 +1071,7 @@ public class MessageListFragment extends ListFragment
// Start loading...
final LoaderManager lm = getLoaderManager();
// If we're loading a different mailbox, discard the previous result.
// It also causes not to preserve the list position.
boolean mailboxChanging = false;
if ((mLastLoadedMailboxId != -1) && (mLastLoadedMailboxId != mMailboxId)) {
mailboxChanging = true;
stopLoaders();
}
lm.initLoader(LOADER_ID_MAILBOX_LOADER, null,
new MailboxAccountLoaderCallback(mailboxChanging));
}
private void stopLoaders() {
final LoaderManager lm = getLoaderManager();
lm.destroyLoader(LOADER_ID_MAILBOX_LOADER);
lm.destroyLoader(LOADER_ID_MESSAGES_LOADER);
lm.initLoader(LOADER_ID_MAILBOX_LOADER, null, new MailboxAccountLoaderCallback());
}
/**
@ -1129,12 +1079,6 @@ public class MessageListFragment extends ListFragment
*/
private class MailboxAccountLoaderCallback implements LoaderManager.LoaderCallbacks<
MailboxAccountLoader.Result> {
private boolean mMailboxChanging;
public MailboxAccountLoaderCallback(boolean mailboxChanging) {
mMailboxChanging = mailboxChanging;
}
@Override
public Loader<MailboxAccountLoader.Result> onCreateLoader(int id, Bundle args) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
@ -1156,17 +1100,13 @@ public class MessageListFragment extends ListFragment
return;
}
mLastLoadedMailboxId = mMailboxId;
mAccount = result.mAccount;
mMailbox = result.mMailbox;
mIsEasAccount = result.mIsEasAccount;
mIsRefreshable = result.mIsRefreshable;
mCountTotalAccounts = result.mCountTotalAccounts;
getLoaderManager().initLoader(LOADER_ID_MESSAGES_LOADER, null,
new MessagesLoaderCallback(mMailboxChanging));
// Clear this for next reload triggered by content changed events.
mMailboxChanging = false;
new MessagesLoaderCallback());
}
@Override
@ -1174,23 +1114,11 @@ public class MessageListFragment extends ListFragment
}
}
/**
* Reload the data and refresh the list view.
*/
private void refreshList() {
getLoaderManager().restartLoader(LOADER_ID_MESSAGES_LOADER, null,
new MessagesLoaderCallback(false));
}
/**
* Loader callbacks for message list.
*/
private class MessagesLoaderCallback implements LoaderManager.LoaderCallbacks<Cursor> {
private boolean mMailboxChanging;
public MessagesLoaderCallback(boolean mailboxChanging) {
mMailboxChanging = mailboxChanging;
}
private boolean mIsFirstLoad;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
@ -1198,6 +1126,7 @@ public class MessageListFragment extends ListFragment
Log.d(Logging.LOG_TAG,
"MessageListFragment onCreateLoader(messages) mailboxId=" + mMailboxId);
}
mIsFirstLoad = true;
return MessagesAdapter.createLoader(getActivity(), mMailboxId);
}
@ -1211,9 +1140,7 @@ public class MessageListFragment extends ListFragment
// Save list view state (primarily scroll position)
final ListView lv = getListView();
final Parcelable listState;
if (mMailboxChanging) {
listState = null; // Don't preserve list state
} else if (mSavedListState != null) {
if (mSavedListState != null) {
listState = mSavedListState;
mSavedListState = null;
} else {
@ -1241,9 +1168,9 @@ public class MessageListFragment extends ListFragment
showSendCommandIfNecessary();
showNoMessageTextIfNecessary();
// We want to make selection visible only when the loader was explicitly started.
// i.e. Refresh caused by content changed events shouldn't scroll the list.
highlightSelectedMessage(mMailboxChanging);
// We want to make visible the selection only for the first load.
// Re-load caused by content changed events shouldn't scroll the list.
highlightSelectedMessage(mIsFirstLoad);
// Restore the state -- this step has to be the last, because Some of the
// "post processing" seems to reset the scroll position.
@ -1254,7 +1181,7 @@ public class MessageListFragment extends ListFragment
resetNewMessageCount(mActivity, mMailboxId, getAccountId());
// Clear this for next reload triggered by content changed events.
mMailboxChanging = false;
mIsFirstLoad = false;
mCallback.onListLoaded();
}
@ -1274,7 +1201,7 @@ public class MessageListFragment extends ListFragment
* accountId} is valid, reset the count of the specified account.
* </ul>
*/
/* protected */static void resetNewMessageCount(
private static void resetNewMessageCount(
Context context, long mailboxId, long accountId) {
if (mailboxId == Mailbox.QUERY_ALL_INBOXES) {
MailService.resetNewMessageCount(context, -1);