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 30632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Account; 31632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Conversation; 32632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Folder; 3350ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwalimport com.android.mail.providers.FolderObserver; 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; 40632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.utils.LogUtils; 41632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 427d64612104fd861474a09994f13768360f92041dAndy Huangpublic class ConversationPagerAdapter extends FragmentStatePagerAdapter2 437d64612104fd861474a09994f13768360f92041dAndy Huang implements ViewPager.OnPageChangeListener { 44632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 45632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final DataSetObserver mListObserver = new ListObserver(); 4650ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal private final FolderObserver mFolderObserver = new FolderObserver() { 4750ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal @Override 4850ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal public void onChanged(Folder newFolder) { 4950ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal notifyDataSetChanged(); 5050ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal } 5150ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal }; 52090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang private ActivityController mController; 53632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final Bundle mCommonFragmentArgs; 54632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final Conversation mInitialConversation; 55b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang private final Account mAccount; 56b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang private final Folder mFolder; 57632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang /** 58632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * In singleton mode, this adapter ignores the cursor contents and size, and acts as if the 591ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang * data set size is exactly size=1, with {@link #getDefaultConversation()} at position 0. 60632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 61d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private boolean mSingletonMode = false; 62632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang /** 631ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang * Similar to singleton mode, but once enabled, detached mode is permanent for this adapter. 641ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang */ 651ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private boolean mDetachedMode = false; 661ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang /** 67d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang * True iff we are in the process of handling a dataset change. 68632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 69d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private boolean mInDataSetChange = false; 7022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang /** 7122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * Need to keep this around to look up pager title strings. 7222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang */ 7322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang private Resources mResources; 7422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang /** 7522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * This isn't great to create a circular dependency, but our usage of {@link #getPageTitle(int)} 7622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * requires knowing which page is the currently visible to dynamically name offscreen pages 7722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * "newer" and "older". And {@link #setPrimaryItem(ViewGroup, int, Object)} does not work well 7822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * because it isn't updated as often as {@link ViewPager#getCurrentItem()} is. 7922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * <p> 8022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * We must be careful to null out this reference when the pager and adapter are decoupled to 8122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * minimize dangling references. 8222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang */ 8322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang private ViewPager mPager; 84f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp private boolean mSanitizedHtml; 85632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 862821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang private boolean mStopListeningMode = false; 872821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 882821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang /** 892821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * After {@link #stopListening()} is called, this contains the last-known count of this adapter. 902821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * We keep this around and use it in lieu of the Cursor's true count until imminent destruction 912821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * to satisfy two opposing requirements: 922821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <ol> 932821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <li>The ViewPager always likes to know about all dataset changes via notifyDatasetChanged. 942821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <li>Destructive changes during pager destruction (e.g. mode transition from conversation mode 952821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * to list mode) must be ignored, or else ViewPager will shift focus onto a neighboring 962821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * conversation and <b>mark it read</b>. 972821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * </ol> 982821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * 992821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang */ 1002821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang private int mLastKnownCount; 1012821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 102d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private static final String LOG_TAG = ConversationPagerController.LOG_TAG; 103632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 1041ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private static final String BUNDLE_DETACHED_MODE = 1051ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang ConversationPagerAdapter.class.getName() + "-detachedmode"; 1061ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 10722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang public ConversationPagerAdapter(Resources res, FragmentManager fm, Account account, 10822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang Folder folder, Conversation initialConversation) { 109632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super(fm, false /* enableSavedStates */); 11022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang mResources = res; 111606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein mCommonFragmentArgs = AbstractConversationViewFragment.makeBasicArgs(account); 112632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mInitialConversation = initialConversation; 113b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang mAccount = account; 114b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang mFolder = folder; 115f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp mSanitizedHtml = mAccount.supportsCapability 116f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp (UIProvider.AccountCapabilities.SANITIZED_HTML); 117b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang } 118b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang 119b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang public boolean matches(Account account, Folder folder) { 120b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang return mAccount != null && mFolder != null && mAccount.matches(account) 121b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang && mFolder.equals(folder); 122632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 123632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 124632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setSingletonMode(boolean enabled) { 125632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang if (mSingletonMode != enabled) { 126632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mSingletonMode = enabled; 127632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang notifyDataSetChanged(); 128632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 129632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 130632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 131632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public boolean isSingletonMode() { 1321ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return mSingletonMode; 1331ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 1341ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 13577fb5be70d76f22a64850aa7a40f6a9553960e4emindyp public boolean isDetached() { 13677fb5be70d76f22a64850aa7a40f6a9553960e4emindyp return mDetachedMode; 13777fb5be70d76f22a64850aa7a40f6a9553960e4emindyp } 13877fb5be70d76f22a64850aa7a40f6a9553960e4emindyp 1395440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal /** 1405440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * Returns true if singleton mode or detached mode have been enabled, or if the current cursor 1415440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * is null. 1425440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * @param cursor the current conversation cursor (obtained through {@link #getCursor()}. 1435440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * @return 1445440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal */ 1455440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal public boolean isPagingDisabled(Cursor cursor) { 1465440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal return mSingletonMode || mDetachedMode || cursor == null; 147e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang } 148e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 1494de145bb568b6963d374fa0bac199218dc494186Paul Westbrook private ConversationCursor getCursor() { 150a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal if (mDetachedMode) { 151a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // In detached mode, the pager is decoupled from the cursor. Nothing should rely on the 152a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // cursor at this point. 153a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal return null; 154a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal } 155090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang if (mController == null) { 156192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // Happens when someone calls setActivityController(null) on us. This is done in 157192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // ConversationPagerController.stopListening() to indicate that the Conversation View 158192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // is going away *very* soon. 1593825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang LogUtils.i(LOG_TAG, "Pager adapter has a null controller. If the conversation view" 160192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal + " is going away, this is fine. Otherwise, the state is inconsistent"); 1618775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return null; 162e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang } 163e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 164090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang return mController.getConversationListCursor(); 165632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 166632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 167632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 168632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public Fragment getItem(int position) { 169632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang final Conversation c; 170983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook final ConversationCursor cursor = getCursor(); 171632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 1725440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 173632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // cursor-less adapter is a size-1 cursor that points to mInitialConversation. 174632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // sanity-check 175632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang if (position != 0) { 176632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "pager cursor is null and position is non-zero: %d", 177632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang position); 178632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 1791ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang c = getDefaultConversation(); 180c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal c.position = 0; 181632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } else { 182e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang if (!cursor.moveToPosition(position)) { 183632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "unable to seek to ConversationCursor pos=%d (%s)", position, 184e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang cursor); 185632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return null; 186632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 187983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook cursor.notifyUIPositionChange(); 18807fe8df87bde8732398434e55cce366a8528c181Andy Huang c = cursor.getConversation(); 189c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal c.position = position; 190632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 191589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy final AbstractConversationViewFragment f = getConversationViewFragment(c); 192d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.getItem, frag=%s conv=%s this=%s", f, c, this); 193632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return f; 194632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 195632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 196f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp private AbstractConversationViewFragment getConversationViewFragment(Conversation c) { 197f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp if (mSanitizedHtml) { 198f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp return ConversationViewFragment.newInstance(mCommonFragmentArgs, c); 199f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } else { 200f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp return SecureConversationViewFragment.newInstance(mCommonFragmentArgs, c); 201f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 202f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 203f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp 204632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 205632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getCount() { 2062821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mStopListeningMode) { 2076b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) { 2086b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang final Cursor cursor = getCursor(); 2096b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang LogUtils.d(LOG_TAG, 2106b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang "IN CPA.getCount stopListeningMode, returning lastKnownCount=%d." 2116b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang + " cursor=%s real count=%s", mLastKnownCount, cursor, 2126b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang (cursor != null) ? cursor.getCount() : "N/A"); 2136b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang } 2142821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang return mLastKnownCount; 2152821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 2162821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 2175440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final Cursor cursor = getCursor(); 2185440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 2193825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang LogUtils.d(LOG_TAG, "IN CPA.getCount, returning 1 (effective singleton). cursor=%s", 2205440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal cursor); 2218775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return 1; 2228775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang } 2238775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return cursor.getCount(); 224632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 225632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 226632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 227632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getItemPosition(Object item) { 228f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp if (!(item instanceof AbstractConversationViewFragment)) { 229632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "getItemPosition received unexpected item: %s", item); 230632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 231632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 232f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item; 233632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return getConversationPosition(fragment.getConversation()); 234632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 235632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 236632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 237632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setPrimaryItem(ViewGroup container, int position, Object object) { 238632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.setPrimaryItem, pos=%d, frag=%s", position, 239632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang object); 240632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.setPrimaryItem(container, position, object); 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) { 256632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.restoreState(state, loader); 2571ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (state != null) { 2581ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Bundle b = (Bundle) state; 2591ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang b.setClassLoader(loader); 260d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang final boolean detached = b.getBoolean(BUNDLE_DETACHED_MODE); 261d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang setDetachedMode(detached); 2621ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 263d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "OUT PagerAdapter.restoreState. this=%s", this); 264632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 265632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 266d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private void setDetachedMode(boolean detached) { 267d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (mDetachedMode == detached) { 268d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang return; 269d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 270d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mDetachedMode = detached; 271d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (mDetachedMode) { 272d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mController.setDetachedMode(); 273d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 274d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang notifyDataSetChanged(); 275632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 276632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 277632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 278d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang public String toString() { 279d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang final StringBuilder sb = new StringBuilder(super.toString()); 280d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.setLength(sb.length() - 1); 281d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" detachedMode="); 282d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mDetachedMode); 283d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" singletonMode="); 284d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mSingletonMode); 285d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mController="); 286d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mController); 287d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mPager="); 288d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mPager); 289d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mStopListening="); 290d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mStopListeningMode); 291d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mLastKnownCount="); 292d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mLastKnownCount); 293d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" cursor="); 294d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(getCursor()); 295d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append("}"); 296d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang return sb.toString(); 297632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 298632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 299632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 300632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void notifyDataSetChanged() { 301d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (mInDataSetChange) { 302d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.i(LOG_TAG, "CPA ignoring dataset change generated during dataset change"); 303632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return; 304632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 3051ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 306d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mInDataSetChange = true; 307a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // If we are in detached mode, changes to the cursor are of no interest to us, but they may 308a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // be to parent classes. 309a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal 3101ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // when the currently visible item disappears from the dataset: 3111ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // if the new version of the currently visible item has zero messages: 3121ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // notify the list controller so it can handle this 'current conversation gone' case 3131ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // (by backing out of conversation mode) 3141ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // else 3151ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // 'detach' the conversation view from the cursor, keeping the current item as-is but 3161ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // disabling swipe (effectively the same as singleton mode) 317b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy if (mController != null && !mDetachedMode && mPager != null) { 3181ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang final Conversation currConversation = mController.getCurrentConversation(); 3191ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang final int pos = getConversationPosition(currConversation); 32007fe8df87bde8732398434e55cce366a8528c181Andy Huang final ConversationCursor cursor = getCursor(); 321631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal if (pos == POSITION_NONE && cursor != null && currConversation != null) { 3221ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // enable detached mode and do no more here. the fragment itself will figure out 3231ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // if the conversation is empty (using message list cursor) and back out if needed. 324d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang setDetachedMode(true); 3251ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang LogUtils.i(LOG_TAG, "CPA: current conv is gone, reverting to detached mode. c=%s", 3261ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang currConversation.uri); 32718176786f320b4d4312ad1682da057434f201c13Scott Kennedy 3280558150910ece60b2d8abf1104338e8ffbb0ea17Scott Kennedy final int currentItem = mPager.getCurrentItem(); 329b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy 330b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy final AbstractConversationViewFragment fragment = 331b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy (AbstractConversationViewFragment) getFragmentAt(currentItem); 332b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy 333b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy if (fragment != null) { 334b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy fragment.onDetachedModeEntered(); 335b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy } else { 336b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy LogUtils.e(LOG_TAG, 337b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy "CPA: notifyDataSetChanged: fragment null, current item: %d", 338b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy currentItem); 339b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy } 34036280f3c2939bb2dacb4077bd528900346ff4bb9mindyp } else { 341631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal // notify unaffected fragment items of the change, so they can re-render 342631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal // (the change may have been to the labels for a single conversation, for example) 343631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal final AbstractConversationViewFragment frag = (cursor == null) ? null : 34426d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp (AbstractConversationViewFragment) getFragmentAt(pos); 3459d3fd92ed6091dbd0d38799222a1cf841f1c3f29Andy Huang if (frag != null && cursor.moveToPosition(pos) && frag.isUserVisible()) { 34616982472f8431aecfdb5f32aa7a97dce9064ac22mindyp // reload what we think is in the current position. 34707fe8df87bde8732398434e55cce366a8528c181Andy Huang final Conversation conv = cursor.getConversation(); 348a825aae102a6112a0b4395eb3c5417c7b0c24262mindyp conv.position = pos; 349b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp frag.onConversationUpdated(conv); 350b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp mController.setCurrentConversation(conv); 35116982472f8431aecfdb5f32aa7a97dce9064ac22mindyp } 3521ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 353d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } else { 354d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "in CPA.notifyDataSetChanged, doing nothing. this=%s", this); 3551ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3561ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 357632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.notifyDataSetChanged(); 358d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mInDataSetChange = false; 359632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 360632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 361632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 362632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setItemVisible(Fragment item, boolean visible) { 363632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.setItemVisible(item, visible); 364f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item; 365632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang fragment.setExtraUserVisibleHint(visible); 366632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 367632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 3681ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private Conversation getDefaultConversation() { 3691ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Conversation c = (mController != null) ? mController.getCurrentConversation() : null; 3701ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (c == null) { 3711ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang c = mInitialConversation; 3721ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3731ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return c; 3741ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3751ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 376632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getConversationPosition(Conversation conv) { 377d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (conv == null) { 378d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang return POSITION_NONE; 379d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 380d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang 3815440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final ConversationCursor cursor = getCursor(); 3825440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 383d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang final Conversation def = getDefaultConversation(); 384d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (!conv.equals(def)) { 385d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "unable to find conversation in singleton mode. c=%s def=%s", 386d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang conv, def); 387632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return POSITION_NONE; 388632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 389d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "in CPA.getConversationPosition returning 0, conv=%s this=%s", 390d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang conv, this); 391632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return 0; 392632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 393632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 3945440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal // cursor is guaranteed to be non-null because isPagingDisabled() above checks for null 3955440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal // cursor. 396e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 397ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang int result = POSITION_NONE; 398c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook final int pos = cursor.getConversationPosition(conv.id); 399c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook if (pos >= 0) { 4009e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang LogUtils.d(LOG_TAG, "pager adapter found repositioned convo %s at pos=%d", 4019e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang conv, pos); 402c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook result = pos; 403ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang } 404ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang 405d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "in CPA.getConversationPosition (normal), conv=%s pos=%s this=%s", 406d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang conv, result, this); 407ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang return result; 408632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 409632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 41022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang public void setPager(ViewPager pager) { 4117d64612104fd861474a09994f13768360f92041dAndy Huang if (mPager != null) { 4127d64612104fd861474a09994f13768360f92041dAndy Huang mPager.setOnPageChangeListener(null); 4137d64612104fd861474a09994f13768360f92041dAndy Huang } 41422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang mPager = pager; 4157d64612104fd861474a09994f13768360f92041dAndy Huang if (mPager != null) { 4167d64612104fd861474a09994f13768360f92041dAndy Huang mPager.setOnPageChangeListener(this); 4177d64612104fd861474a09994f13768360f92041dAndy Huang } 41822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang } 41922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang 420090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang public void setActivityController(ActivityController controller) { 421d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang boolean wasNull = (mController == null); 4222821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null && !mStopListeningMode) { 423090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController.unregisterConversationListObserver(mListObserver); 424860164409d7f9e4f726ed4edb2ed77afc6873ad5Andy Huang mController.unregisterFolderObserver(mFolderObserver); 425632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 426090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController = controller; 4272821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null && !mStopListeningMode) { 428090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController.registerConversationListObserver(mListObserver); 42950ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal mFolderObserver.initialize(mController); 430d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (!wasNull) { 431d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang notifyDataSetChanged(); 432d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 433632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } else { 434e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang // We're being torn down; do not notify. 435e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang // Let the pager controller manage pager lifecycle. 436632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 437632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 438632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 4392821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang /** 4402821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * See {@link ConversationPagerController#stopListening()}. 4412821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang */ 4422821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang public void stopListening() { 443647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang if (mStopListeningMode) { 444647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang // Do nothing since we're already in stop listening mode. This avoids repeated 445647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang // unregister observer calls. 446647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang return; 447647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang } 448647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang 4492821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang // disable the observer, but save off the current count, in case the Pager asks for it 4502821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang // from now until imminent destruction 4512821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 4522821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null) { 4532821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mController.unregisterConversationListObserver(mListObserver); 45450ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal mFolderObserver.unregisterAndDestroy(); 4552821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 4562821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mLastKnownCount = getCount(); 4576b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang mStopListeningMode = true; 458d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "CPA.stopListening, this=%s", this); 4592821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 4602821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 4617d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4627d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 4637d64612104fd861474a09994f13768360f92041dAndy Huang // no-op 4647d64612104fd861474a09994f13768360f92041dAndy Huang } 4657d64612104fd861474a09994f13768360f92041dAndy Huang 4667d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4677d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageSelected(int position) { 46866db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal if (mController == null) { 46966db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal return; 47066db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal } 47107fe8df87bde8732398434e55cce366a8528c181Andy Huang final ConversationCursor cursor = getCursor(); 47266db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal if (cursor == null || !cursor.moveToPosition(position)) { 47366db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal // No valid cursor or it doesn't have the position we want. Bail. 47466db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal return; 4757d64612104fd861474a09994f13768360f92041dAndy Huang } 47607fe8df87bde8732398434e55cce366a8528c181Andy Huang final Conversation c = cursor.getConversation(); 47766db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal c.position = position; 4789e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang LogUtils.d(LOG_TAG, "pager adapter setting current conv: %s", c); 47966db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal mController.setCurrentConversation(c); 4807d64612104fd861474a09994f13768360f92041dAndy Huang } 4817d64612104fd861474a09994f13768360f92041dAndy Huang 4827d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4837d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageScrollStateChanged(int state) { 4847d64612104fd861474a09994f13768360f92041dAndy Huang // no-op 4857d64612104fd861474a09994f13768360f92041dAndy Huang } 4867d64612104fd861474a09994f13768360f92041dAndy Huang 487632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // update the pager dataset as the Controller's cursor changes 488632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private class ListObserver extends DataSetObserver { 489632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 490632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void onChanged() { 491e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang notifyDataSetChanged(); 492632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 493632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 494632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void onInvalidated() { 495632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 496632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 497632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 498632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang} 499