ConversationPagerAdapter.java revision 18176786f320b4d4312ad1682da057434f201c13
1632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang/*
2632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Copyright (C) 2012 Google Inc.
3632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Licensed to The Android Open Source Project.
4632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang *
5632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Licensed under the Apache License, Version 2.0 (the "License");
6632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * you may not use this file except in compliance with the License.
7632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * You may obtain a copy of the License at
8632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang *
9632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang *      http://www.apache.org/licenses/LICENSE-2.0
10632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang *
11632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Unless required by applicable law or agreed to in writing, software
12632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * distributed under the License is distributed on an "AS IS" BASIS,
13632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * See the License for the specific language governing permissions and
15632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * limitations under the License.
16632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */
17632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
18632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangpackage com.android.mail.browse;
19632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
20632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.app.Fragment;
21632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.app.FragmentManager;
2222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huangimport android.content.res.Resources;
23632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.database.Cursor;
24632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.database.DataSetObserver;
25632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.os.Bundle;
26632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.os.Parcelable;
2722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huangimport android.support.v4.view.ViewPager;
28632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.view.ViewGroup;
29632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
3022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huangimport com.android.mail.R;
31632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Account;
32632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Conversation;
33632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Folder;
34632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.UIProvider;
35f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport com.android.mail.ui.AbstractConversationViewFragment;
36090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huangimport com.android.mail.ui.ActivityController;
37632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.ui.ConversationViewFragment;
38351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huangimport com.android.mail.ui.SecureConversationViewFragment;
39632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.utils.FragmentStatePagerAdapter2;
40b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
41632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.utils.LogUtils;
42632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
437d64612104fd861474a09994f13768360f92041dAndy Huangpublic class ConversationPagerAdapter extends FragmentStatePagerAdapter2
447d64612104fd861474a09994f13768360f92041dAndy Huang        implements ViewPager.OnPageChangeListener {
45632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
46632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    private final DataSetObserver mListObserver = new ListObserver();
47090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang    private final DataSetObserver mFolderObserver = new FolderObserver();
48090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang    private ActivityController mController;
49632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    private final Bundle mCommonFragmentArgs;
50632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    private final Conversation mInitialConversation;
51b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang    private final Account mAccount;
52b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang    private final Folder mFolder;
53632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    /**
54632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * In singleton mode, this adapter ignores the cursor contents and size, and acts as if the
551ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * data set size is exactly size=1, with {@link #getDefaultConversation()} at position 0.
56632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     */
57632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    private boolean mSingletonMode = true;
58632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    /**
591ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * Similar to singleton mode, but once enabled, detached mode is permanent for this adapter.
601ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     */
611ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    private boolean mDetachedMode = false;
621ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    /**
63632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * Adapter methods may trigger a data set change notification in the middle of a ViewPager
64632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * update, but they are not safe to handle, so we have to ignore them. This will not ignore
65632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * pager-external updates; it's impossible to be notified of an external change during
66632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * an update.
67632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     *
68632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * TODO: Queue up changes like this, if there ever are any that actually modify the data set.
69632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * Right now there are none. Such a change would have to be of the form: instantiation or
70632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     * setPrimary somehow adds or removes items from the conversation cursor. Crazy!
71632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang     */
72632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    private boolean mSafeToNotify;
7322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang    /**
7422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * Need to keep this around to look up pager title strings.
7522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     */
7622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang    private Resources mResources;
7722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang    /**
7822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * This isn't great to create a circular dependency, but our usage of {@link #getPageTitle(int)}
7922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * requires knowing which page is the currently visible to dynamically name offscreen pages
8022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * "newer" and "older". And {@link #setPrimaryItem(ViewGroup, int, Object)} does not work well
8122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * because it isn't updated as often as {@link ViewPager#getCurrentItem()} is.
8222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * <p>
8322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * We must be careful to null out this reference when the pager and adapter are decoupled to
8422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     * minimize dangling references.
8522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang     */
8622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang    private ViewPager mPager;
87f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    private boolean mSanitizedHtml;
88632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
89b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    private static final String LOG_TAG = LogTag.getLogTag();
90632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
911ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    private static final String BUNDLE_DETACHED_MODE =
921ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            ConversationPagerAdapter.class.getName() + "-detachedmode";
931ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
9422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang    public ConversationPagerAdapter(Resources res, FragmentManager fm, Account account,
9522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang            Folder folder, Conversation initialConversation) {
96632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super(fm, false /* enableSavedStates */);
9722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang        mResources = res;
98f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        mCommonFragmentArgs = AbstractConversationViewFragment.makeBasicArgs(account, folder);
99632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        mInitialConversation = initialConversation;
100b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang        mAccount = account;
101b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang        mFolder = folder;
102f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        mSanitizedHtml = mAccount.supportsCapability
103f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp                (UIProvider.AccountCapabilities.SANITIZED_HTML);
104b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang    }
105b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang
106b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang    public boolean matches(Account account, Folder folder) {
107b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang        return mAccount != null && mFolder != null && mAccount.matches(account)
108b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang                && mFolder.equals(folder);
109632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
110632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
111632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void setSingletonMode(boolean enabled) {
112632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        if (mSingletonMode != enabled) {
113632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            mSingletonMode = enabled;
114632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            notifyDataSetChanged();
115632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
116632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
117632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
118632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public boolean isSingletonMode() {
1191ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        return mSingletonMode;
1201ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    }
1211ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
12277fb5be70d76f22a64850aa7a40f6a9553960e4emindyp    public boolean isDetached() {
12377fb5be70d76f22a64850aa7a40f6a9553960e4emindyp        return mDetachedMode;
12477fb5be70d76f22a64850aa7a40f6a9553960e4emindyp    }
12577fb5be70d76f22a64850aa7a40f6a9553960e4emindyp
1265440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal    /**
1275440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal     * Returns true if singleton mode or detached mode have been enabled, or if the current cursor
1285440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal     * is null.
1295440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal     * @param cursor the current conversation cursor (obtained through {@link #getCursor()}.
1305440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal     * @return
1315440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal     */
1325440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal    public boolean isPagingDisabled(Cursor cursor) {
1335440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        return mSingletonMode || mDetachedMode || cursor == null;
134e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang    }
135e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang
1364de145bb568b6963d374fa0bac199218dc494186Paul Westbrook    private ConversationCursor getCursor() {
137a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal        if (mDetachedMode) {
138a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal            // In detached mode, the pager is decoupled from the cursor. Nothing should rely on the
139a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal            // cursor at this point.
140a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal            return null;
141a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal        }
142090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        if (mController == null) {
143192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal            // Happens when someone calls setActivityController(null) on us. This is done in
144192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal            // ConversationPagerController.stopListening() to indicate that the Conversation View
145192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal            // is going away *very* soon.
1463825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang            LogUtils.i(LOG_TAG, "Pager adapter has a null controller. If the conversation view"
147192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal                    + " is going away, this is fine.  Otherwise, the state is inconsistent");
1488775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang            return null;
149e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang        }
150e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang
151090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        return mController.getConversationListCursor();
152632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
153632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
154632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
155632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public Fragment getItem(int position) {
156632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        final Conversation c;
1575440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        final Cursor cursor = getCursor();
158632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
1595440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        if (isPagingDisabled(cursor)) {
160632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            // cursor-less adapter is a size-1 cursor that points to mInitialConversation.
161632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            // sanity-check
162632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            if (position != 0) {
163632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang                LogUtils.wtf(LOG_TAG, "pager cursor is null and position is non-zero: %d",
164632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang                        position);
165632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            }
1661ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            c = getDefaultConversation();
167c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal            c.position = 0;
168632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        } else {
169e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang            if (!cursor.moveToPosition(position)) {
170632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang                LogUtils.wtf(LOG_TAG, "unable to seek to ConversationCursor pos=%d (%s)", position,
171e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang                        cursor);
172632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang                return null;
173632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            }
174632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            // TODO: switch to something like MessageCursor or AttachmentCursor
175632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            // to re-use these models
176e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang            c = new Conversation(cursor);
177c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal            c.position = position;
178632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
179f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        final Fragment f = getConversationViewFragment(c);
180632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        LogUtils.d(LOG_TAG, "IN PagerAdapter.getItem, frag=%s subj=%s", f, c.subject);
181632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        return f;
182632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
183632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
184f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    private AbstractConversationViewFragment getConversationViewFragment(Conversation c) {
185f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        if (mSanitizedHtml) {
186f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp            return ConversationViewFragment.newInstance(mCommonFragmentArgs, c);
187f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        } else {
188f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp            return SecureConversationViewFragment.newInstance(mCommonFragmentArgs, c);
189f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        }
190f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
191f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
192632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
193632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public int getCount() {
1945440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        final Cursor cursor = getCursor();
1955440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        if (isPagingDisabled(cursor)) {
1963825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang            LogUtils.d(LOG_TAG, "IN CPA.getCount, returning 1 (effective singleton). cursor=%s",
1975440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal                    cursor);
1988775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang            return 1;
1998775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang        }
2008775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang        return cursor.getCount();
201632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
202632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
203632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
204632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public int getItemPosition(Object item) {
205f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        if (!(item instanceof AbstractConversationViewFragment)) {
206632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            LogUtils.wtf(LOG_TAG, "getItemPosition received unexpected item: %s", item);
207632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
208632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
209f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item;
210632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        return getConversationPosition(fragment.getConversation());
211632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
212632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
213632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
214632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void setPrimaryItem(ViewGroup container, int position, Object object) {
215632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        LogUtils.d(LOG_TAG, "IN PagerAdapter.setPrimaryItem, pos=%d, frag=%s", position,
216632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang                object);
217632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super.setPrimaryItem(container, position, object);
218632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
219632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
220632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
221632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public CharSequence getPageTitle(int position) {
22222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang        final String title;
22322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang        final int currentPosition = mPager.getCurrentItem();
2245440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        final Cursor cursor = getCursor();
2255440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        if (isPagingDisabled(cursor)) {
22668459a7b3265da5002ff331529f12f6b408c9b03Andy Huang            title = null;
22768459a7b3265da5002ff331529f12f6b408c9b03Andy Huang        } else if (position == currentPosition) {
228090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang            int total = getCount();
229090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang            if (mController != null) {
230090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang                final Folder f = mController.getFolder();
231090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang                if (f != null && f.totalCount > total) {
232090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang                    total = f.totalCount;
233090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang                }
234090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang            }
235090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang            title = mResources.getString(R.string.conversation_count, position + 1, total);
23622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang        } else {
23768459a7b3265da5002ff331529f12f6b408c9b03Andy Huang            title = mResources.getString(position < currentPosition ?
23822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang                    R.string.conversation_newer : R.string.conversation_older);
23922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang        }
24022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang        return title;
241632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
242632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
243632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
244632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public Parcelable saveState() {
2451ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        LogUtils.d(LOG_TAG, "IN PagerAdapter.saveState. this=%s", this);
2461ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        Bundle state = (Bundle) super.saveState(); // superclass uses a Bundle
2471ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        if (state == null) {
2481ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            state = new Bundle();
2491ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
2501ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        state.putBoolean(BUNDLE_DETACHED_MODE, mDetachedMode);
2511ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        return state;
252632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
253632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
254632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
255632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void restoreState(Parcelable state, ClassLoader loader) {
2561ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        LogUtils.d(LOG_TAG, "IN PagerAdapter.restoreState. this=%s", this);
257632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super.restoreState(state, loader);
2581ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        if (state != null) {
2591ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            Bundle b = (Bundle) state;
2601ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            b.setClassLoader(loader);
2611ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            mDetachedMode = b.getBoolean(BUNDLE_DETACHED_MODE);
2621ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
263632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
264632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
265632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
266632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void startUpdate(ViewGroup container) {
267632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        mSafeToNotify = false;
268632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super.startUpdate(container);
269632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
270632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
271632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
272632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void finishUpdate(ViewGroup container) {
273632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super.finishUpdate(container);
274632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        mSafeToNotify = true;
275632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
276632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
277632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
278632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void notifyDataSetChanged() {
279632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        if (!mSafeToNotify) {
280632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            LogUtils.d(LOG_TAG, "IN PagerAdapter.notifyDataSetChanged, ignoring unsafe update");
281632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            return;
282632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
2831ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
284a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal        // If we are in detached mode, changes to the cursor are of no interest to us, but they may
285a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal        // be to parent classes.
286a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal
2871ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        // when the currently visible item disappears from the dataset:
2881ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        //   if the new version of the currently visible item has zero messages:
2891ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        //     notify the list controller so it can handle this 'current conversation gone' case
2901ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        //     (by backing out of conversation mode)
2911ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        //   else
2921ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        //     'detach' the conversation view from the cursor, keeping the current item as-is but
2931ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        //     disabling swipe (effectively the same as singleton mode)
294a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal        if (mController != null && !mDetachedMode) {
2951ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            final Conversation currConversation = mController.getCurrentConversation();
2961ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            final int pos = getConversationPosition(currConversation);
297631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal            final Cursor cursor = getCursor();
298631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal            if (pos == POSITION_NONE && cursor != null && currConversation != null) {
2991ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                // enable detached mode and do no more here. the fragment itself will figure out
3001ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                // if the conversation is empty (using message list cursor) and back out if needed.
3011ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                mDetachedMode = true;
302a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal                mController.setDetachedMode();
3031ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                LogUtils.i(LOG_TAG, "CPA: current conv is gone, reverting to detached mode. c=%s",
3041ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                        currConversation.uri);
30518176786f320b4d4312ad1682da057434f201c13Scott Kennedy
30618176786f320b4d4312ad1682da057434f201c13Scott Kennedy                ((AbstractConversationViewFragment) getFragmentAt(mPager.getCurrentItem()))
30718176786f320b4d4312ad1682da057434f201c13Scott Kennedy                        .onDetachedModeEntered();
30836280f3c2939bb2dacb4077bd528900346ff4bb9mindyp            } else {
309631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal                // notify unaffected fragment items of the change, so they can re-render
310631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal                // (the change may have been to the labels for a single conversation, for example)
311631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal                final AbstractConversationViewFragment frag = (cursor == null) ? null :
31226d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp                        (AbstractConversationViewFragment) getFragmentAt(pos);
3139d3fd92ed6091dbd0d38799222a1cf841f1c3f29Andy Huang                if (frag != null && cursor.moveToPosition(pos) && frag.isUserVisible()) {
31416982472f8431aecfdb5f32aa7a97dce9064ac22mindyp                    // reload what we think is in the current position.
315631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal                    final Conversation conv = new Conversation(cursor);
316a825aae102a6112a0b4395eb3c5417c7b0c24262mindyp                    conv.position = pos;
317b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp                    frag.onConversationUpdated(conv);
318b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp                    mController.setCurrentConversation(conv);
31916982472f8431aecfdb5f32aa7a97dce9064ac22mindyp                }
3201ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            }
3211ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
3221ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
323632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super.notifyDataSetChanged();
324632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
325632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
326632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    @Override
327632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void setItemVisible(Fragment item, boolean visible) {
328632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super.setItemVisible(item, visible);
329f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item;
330632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        fragment.setExtraUserVisibleHint(visible);
331632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
332632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
3331ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    private Conversation getDefaultConversation() {
3341ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        Conversation c = (mController != null) ? mController.getCurrentConversation() : null;
3351ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        if (c == null) {
3361ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            c = mInitialConversation;
3371ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
3381ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        return c;
3391ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    }
3401ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
341632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public int getConversationPosition(Conversation conv) {
3425440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        final ConversationCursor cursor = getCursor();
3435440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        if (isPagingDisabled(cursor)) {
3441ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            if (conv != getDefaultConversation()) {
34549e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal                LogUtils.d(LOG_TAG, "unable to find conversation in singleton mode. c=%s", conv);
346632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang                return POSITION_NONE;
347632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            }
348632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang            return 0;
349632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
350632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
3515440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        // cursor is guaranteed to be non-null because isPagingDisabled() above checks for null
3525440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        // cursor.
3535440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal        if (conv == null) {
3548775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang            return POSITION_NONE;
3558775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang        }
356e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang
357ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang        int result = POSITION_NONE;
358c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook        final int pos = cursor.getConversationPosition(conv.id);
359c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook        if (pos >= 0) {
360c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook            LogUtils.d(LOG_TAG, "pager adapter found repositioned convo '%s' at pos=%d",
361c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook                    conv.subject, pos);
362c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook            result = pos;
363ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang        }
364ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang
365ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang        return result;
366632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
367632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
36822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang    public void setPager(ViewPager pager) {
3697d64612104fd861474a09994f13768360f92041dAndy Huang        if (mPager != null) {
3707d64612104fd861474a09994f13768360f92041dAndy Huang            mPager.setOnPageChangeListener(null);
3717d64612104fd861474a09994f13768360f92041dAndy Huang        }
37222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang        mPager = pager;
3737d64612104fd861474a09994f13768360f92041dAndy Huang        if (mPager != null) {
3747d64612104fd861474a09994f13768360f92041dAndy Huang            mPager.setOnPageChangeListener(this);
3757d64612104fd861474a09994f13768360f92041dAndy Huang        }
37622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang    }
37722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang
378090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang    public void setActivityController(ActivityController controller) {
379090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        if (mController != null) {
380090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang            mController.unregisterConversationListObserver(mListObserver);
381860164409d7f9e4f726ed4edb2ed77afc6873ad5Andy Huang            mController.unregisterFolderObserver(mFolderObserver);
382632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
383090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        mController = controller;
384090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        if (mController != null) {
385090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang            mController.registerConversationListObserver(mListObserver);
386860164409d7f9e4f726ed4edb2ed77afc6873ad5Andy Huang            mController.registerFolderObserver(mFolderObserver);
387632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
388e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang            notifyDataSetChanged();
389632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        } else {
390e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang            // We're being torn down; do not notify.
391e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang            // Let the pager controller manage pager lifecycle.
392632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
393632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
394632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
3957d64612104fd861474a09994f13768360f92041dAndy Huang    @Override
3967d64612104fd861474a09994f13768360f92041dAndy Huang    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
3977d64612104fd861474a09994f13768360f92041dAndy Huang        // no-op
3987d64612104fd861474a09994f13768360f92041dAndy Huang    }
3997d64612104fd861474a09994f13768360f92041dAndy Huang
4007d64612104fd861474a09994f13768360f92041dAndy Huang    @Override
4017d64612104fd861474a09994f13768360f92041dAndy Huang    public void onPageSelected(int position) {
40266db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        if (mController == null) {
40366db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal            return;
40466db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        }
40566db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        final Cursor cursor = getCursor();
40666db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        if (cursor == null || !cursor.moveToPosition(position)) {
40766db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal            // No valid cursor or it doesn't have the position we want. Bail.
40866db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal            return;
4097d64612104fd861474a09994f13768360f92041dAndy Huang        }
41066db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        final Conversation c = new Conversation(cursor);
41166db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        c.position = position;
41266db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        LogUtils.d(LOG_TAG, "pager adapter setting current conv: %s", c.subject);
41366db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal        mController.setCurrentConversation(c);
4147d64612104fd861474a09994f13768360f92041dAndy Huang    }
4157d64612104fd861474a09994f13768360f92041dAndy Huang
4167d64612104fd861474a09994f13768360f92041dAndy Huang    @Override
4177d64612104fd861474a09994f13768360f92041dAndy Huang    public void onPageScrollStateChanged(int state) {
4187d64612104fd861474a09994f13768360f92041dAndy Huang        // no-op
4197d64612104fd861474a09994f13768360f92041dAndy Huang    }
4207d64612104fd861474a09994f13768360f92041dAndy Huang
421090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang    // update the pager title strip as the Folder's conversation count changes
422090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang    private class FolderObserver extends DataSetObserver {
423090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        @Override
424090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        public void onChanged() {
425090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang            notifyDataSetChanged();
426090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang        }
427090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang    }
428090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang
429632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    // update the pager dataset as the Controller's cursor changes
430632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    private class ListObserver extends DataSetObserver {
431632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        @Override
432632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        public void onChanged() {
433e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang            notifyDataSetChanged();
434632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
435632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        @Override
436632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        public void onInvalidated() {
437632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
438632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    }
439632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
440632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang}
441