ConversationPagerAdapter.java revision 983a723931447b6261a2e42b25e6f931dba6de33
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; 3450ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwalimport com.android.mail.providers.FolderObserver; 35632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.UIProvider; 36f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport com.android.mail.ui.AbstractConversationViewFragment; 37090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huangimport com.android.mail.ui.ActivityController; 38632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.ui.ConversationViewFragment; 39351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huangimport com.android.mail.ui.SecureConversationViewFragment; 40632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.utils.FragmentStatePagerAdapter2; 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(); 4750ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal private final FolderObserver mFolderObserver = new FolderObserver() { 4850ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal @Override 4950ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal public void onChanged(Folder newFolder) { 5050ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal notifyDataSetChanged(); 5150ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal } 5250ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal }; 53090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang private ActivityController mController; 54632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final Bundle mCommonFragmentArgs; 55632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final Conversation mInitialConversation; 56b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang private final Account mAccount; 57b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang private final Folder mFolder; 58632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang /** 59632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * In singleton mode, this adapter ignores the cursor contents and size, and acts as if the 601ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang * data set size is exactly size=1, with {@link #getDefaultConversation()} at position 0. 61632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 62d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private boolean mSingletonMode = false; 63632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang /** 641ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang * Similar to singleton mode, but once enabled, detached mode is permanent for this adapter. 651ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang */ 661ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private boolean mDetachedMode = false; 671ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang /** 68d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang * True iff we are in the process of handling a dataset change. 69632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 70d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private boolean mInDataSetChange = false; 7122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang /** 7222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * Need to keep this around to look up pager title strings. 7322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang */ 7422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang private Resources mResources; 7522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang /** 7622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * This isn't great to create a circular dependency, but our usage of {@link #getPageTitle(int)} 7722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * requires knowing which page is the currently visible to dynamically name offscreen pages 7822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * "newer" and "older". And {@link #setPrimaryItem(ViewGroup, int, Object)} does not work well 7922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * because it isn't updated as often as {@link ViewPager#getCurrentItem()} is. 8022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * <p> 8122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * We must be careful to null out this reference when the pager and adapter are decoupled to 8222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * minimize dangling references. 8322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang */ 8422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang private ViewPager mPager; 85f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp private boolean mSanitizedHtml; 86632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 872821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang private boolean mStopListeningMode = false; 882821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 892821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang /** 902821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * After {@link #stopListening()} is called, this contains the last-known count of this adapter. 912821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * We keep this around and use it in lieu of the Cursor's true count until imminent destruction 922821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * to satisfy two opposing requirements: 932821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <ol> 942821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <li>The ViewPager always likes to know about all dataset changes via notifyDatasetChanged. 952821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <li>Destructive changes during pager destruction (e.g. mode transition from conversation mode 962821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * to list mode) must be ignored, or else ViewPager will shift focus onto a neighboring 972821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * conversation and <b>mark it read</b>. 982821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * </ol> 992821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * 1002821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang */ 1012821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang private int mLastKnownCount; 1022821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 103d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private static final String LOG_TAG = ConversationPagerController.LOG_TAG; 104632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 1051ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private static final String BUNDLE_DETACHED_MODE = 1061ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang ConversationPagerAdapter.class.getName() + "-detachedmode"; 1071ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 10822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang public ConversationPagerAdapter(Resources res, FragmentManager fm, Account account, 10922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang Folder folder, Conversation initialConversation) { 110632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super(fm, false /* enableSavedStates */); 11122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang mResources = res; 112f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp mCommonFragmentArgs = AbstractConversationViewFragment.makeBasicArgs(account, folder); 113632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mInitialConversation = initialConversation; 114b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang mAccount = account; 115b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang mFolder = folder; 116f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp mSanitizedHtml = mAccount.supportsCapability 117f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp (UIProvider.AccountCapabilities.SANITIZED_HTML); 118b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang } 119b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang 120b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang public boolean matches(Account account, Folder folder) { 121b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang return mAccount != null && mFolder != null && mAccount.matches(account) 122b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang && mFolder.equals(folder); 123632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 124632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 125632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setSingletonMode(boolean enabled) { 126632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang if (mSingletonMode != enabled) { 127632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mSingletonMode = enabled; 128632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang notifyDataSetChanged(); 129632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 130632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 131632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 132632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public boolean isSingletonMode() { 1331ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return mSingletonMode; 1341ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 1351ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 13677fb5be70d76f22a64850aa7a40f6a9553960e4emindyp public boolean isDetached() { 13777fb5be70d76f22a64850aa7a40f6a9553960e4emindyp return mDetachedMode; 13877fb5be70d76f22a64850aa7a40f6a9553960e4emindyp } 13977fb5be70d76f22a64850aa7a40f6a9553960e4emindyp 1405440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal /** 1415440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * Returns true if singleton mode or detached mode have been enabled, or if the current cursor 1425440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * is null. 1435440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * @param cursor the current conversation cursor (obtained through {@link #getCursor()}. 1445440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * @return 1455440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal */ 1465440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal public boolean isPagingDisabled(Cursor cursor) { 1475440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal return mSingletonMode || mDetachedMode || cursor == null; 148e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang } 149e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 1504de145bb568b6963d374fa0bac199218dc494186Paul Westbrook private ConversationCursor getCursor() { 151a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal if (mDetachedMode) { 152a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // In detached mode, the pager is decoupled from the cursor. Nothing should rely on the 153a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // cursor at this point. 154a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal return null; 155a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal } 156090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang if (mController == null) { 157192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // Happens when someone calls setActivityController(null) on us. This is done in 158192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // ConversationPagerController.stopListening() to indicate that the Conversation View 159192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // is going away *very* soon. 1603825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang LogUtils.i(LOG_TAG, "Pager adapter has a null controller. If the conversation view" 161192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal + " is going away, this is fine. Otherwise, the state is inconsistent"); 1628775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return null; 163e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang } 164e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 165090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang return mController.getConversationListCursor(); 166632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 167632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 168632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 169632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public Fragment getItem(int position) { 170632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang final Conversation c; 171983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook final ConversationCursor cursor = getCursor(); 172632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 1735440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 174632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // cursor-less adapter is a size-1 cursor that points to mInitialConversation. 175632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // sanity-check 176632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang if (position != 0) { 177632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "pager cursor is null and position is non-zero: %d", 178632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang position); 179632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 1801ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang c = getDefaultConversation(); 181c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal c.position = 0; 182632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } else { 183e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang if (!cursor.moveToPosition(position)) { 184632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "unable to seek to ConversationCursor pos=%d (%s)", position, 185e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang cursor); 186632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return null; 187632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 188983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook cursor.notifyUIPositionChange(); 189632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // TODO: switch to something like MessageCursor or AttachmentCursor 190632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // to re-use these models 191e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang c = new Conversation(cursor); 192c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal c.position = position; 193632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 194589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy final AbstractConversationViewFragment f = getConversationViewFragment(c); 195d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.getItem, frag=%s conv=%s this=%s", f, c, this); 196632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return f; 197632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 198632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 199f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp private AbstractConversationViewFragment getConversationViewFragment(Conversation c) { 200f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp if (mSanitizedHtml) { 201f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp return ConversationViewFragment.newInstance(mCommonFragmentArgs, c); 202f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } else { 203f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp return SecureConversationViewFragment.newInstance(mCommonFragmentArgs, c); 204f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 205f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 206f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp 207632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 208632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getCount() { 2092821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mStopListeningMode) { 2106b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) { 2116b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang final Cursor cursor = getCursor(); 2126b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang LogUtils.d(LOG_TAG, 2136b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang "IN CPA.getCount stopListeningMode, returning lastKnownCount=%d." 2146b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang + " cursor=%s real count=%s", mLastKnownCount, cursor, 2156b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang (cursor != null) ? cursor.getCount() : "N/A"); 2166b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang } 2172821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang return mLastKnownCount; 2182821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 2192821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 2205440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final Cursor cursor = getCursor(); 2215440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 2223825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang LogUtils.d(LOG_TAG, "IN CPA.getCount, returning 1 (effective singleton). cursor=%s", 2235440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal cursor); 2248775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return 1; 2258775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang } 2268775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return cursor.getCount(); 227632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 228632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 229632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 230632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getItemPosition(Object item) { 231f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp if (!(item instanceof AbstractConversationViewFragment)) { 232632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "getItemPosition received unexpected item: %s", item); 233632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 234632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 235f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item; 236632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return getConversationPosition(fragment.getConversation()); 237632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 238632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 239632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 240632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setPrimaryItem(ViewGroup container, int position, Object object) { 241632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.setPrimaryItem, pos=%d, frag=%s", position, 242632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang object); 243632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.setPrimaryItem(container, position, object); 244632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 245632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 246632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 247632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public CharSequence getPageTitle(int position) { 24822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang final String title; 24922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang final int currentPosition = mPager.getCurrentItem(); 2505440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final Cursor cursor = getCursor(); 2515440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 25268459a7b3265da5002ff331529f12f6b408c9b03Andy Huang title = null; 25368459a7b3265da5002ff331529f12f6b408c9b03Andy Huang } else if (position == currentPosition) { 254090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang int total = getCount(); 255090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang if (mController != null) { 256090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang final Folder f = mController.getFolder(); 257090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang if (f != null && f.totalCount > total) { 258090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang total = f.totalCount; 259090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang } 260090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang } 261090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang title = mResources.getString(R.string.conversation_count, position + 1, total); 26222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang } else { 26368459a7b3265da5002ff331529f12f6b408c9b03Andy Huang title = mResources.getString(position < currentPosition ? 26422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang R.string.conversation_newer : R.string.conversation_older); 26522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang } 26622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang return title; 267632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 268632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 269632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 270632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public Parcelable saveState() { 2711ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.saveState. this=%s", this); 2721ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Bundle state = (Bundle) super.saveState(); // superclass uses a Bundle 2731ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (state == null) { 2741ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang state = new Bundle(); 2751ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 2761ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang state.putBoolean(BUNDLE_DETACHED_MODE, mDetachedMode); 2771ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return state; 278632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 279632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 280632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 281632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void restoreState(Parcelable state, ClassLoader loader) { 282632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.restoreState(state, loader); 2831ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (state != null) { 2841ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Bundle b = (Bundle) state; 2851ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang b.setClassLoader(loader); 286d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang final boolean detached = b.getBoolean(BUNDLE_DETACHED_MODE); 287d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang setDetachedMode(detached); 2881ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 289d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "OUT PagerAdapter.restoreState. this=%s", this); 290632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 291632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 292d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang private void setDetachedMode(boolean detached) { 293d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (mDetachedMode == detached) { 294d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang return; 295d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 296d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mDetachedMode = detached; 297d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (mDetachedMode) { 298d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mController.setDetachedMode(); 299d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 300d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang notifyDataSetChanged(); 301632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 302632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 303632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 304d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang public String toString() { 305d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang final StringBuilder sb = new StringBuilder(super.toString()); 306d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.setLength(sb.length() - 1); 307d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" detachedMode="); 308d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mDetachedMode); 309d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" singletonMode="); 310d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mSingletonMode); 311d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mController="); 312d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mController); 313d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mPager="); 314d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mPager); 315d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mStopListening="); 316d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mStopListeningMode); 317d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" mLastKnownCount="); 318d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(mLastKnownCount); 319d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(" cursor="); 320d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append(getCursor()); 321d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang sb.append("}"); 322d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang return sb.toString(); 323632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 324632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 325632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 326632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void notifyDataSetChanged() { 327d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (mInDataSetChange) { 328d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.i(LOG_TAG, "CPA ignoring dataset change generated during dataset change"); 329632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return; 330632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 3311ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 332d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mInDataSetChange = true; 333a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // If we are in detached mode, changes to the cursor are of no interest to us, but they may 334a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // be to parent classes. 335a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal 3361ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // when the currently visible item disappears from the dataset: 3371ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // if the new version of the currently visible item has zero messages: 3381ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // notify the list controller so it can handle this 'current conversation gone' case 3391ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // (by backing out of conversation mode) 3401ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // else 3411ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // 'detach' the conversation view from the cursor, keeping the current item as-is but 3421ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // disabling swipe (effectively the same as singleton mode) 343b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy if (mController != null && !mDetachedMode && mPager != null) { 3441ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang final Conversation currConversation = mController.getCurrentConversation(); 3451ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang final int pos = getConversationPosition(currConversation); 346631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal final Cursor cursor = getCursor(); 347631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal if (pos == POSITION_NONE && cursor != null && currConversation != null) { 3481ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // enable detached mode and do no more here. the fragment itself will figure out 3491ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // if the conversation is empty (using message list cursor) and back out if needed. 350d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang setDetachedMode(true); 3511ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang LogUtils.i(LOG_TAG, "CPA: current conv is gone, reverting to detached mode. c=%s", 3521ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang currConversation.uri); 35318176786f320b4d4312ad1682da057434f201c13Scott Kennedy 3540558150910ece60b2d8abf1104338e8ffbb0ea17Scott Kennedy final int currentItem = mPager.getCurrentItem(); 355b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy 356b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy final AbstractConversationViewFragment fragment = 357b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy (AbstractConversationViewFragment) getFragmentAt(currentItem); 358b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy 359b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy if (fragment != null) { 360b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy fragment.onDetachedModeEntered(); 361b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy } else { 362b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy LogUtils.e(LOG_TAG, 363b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy "CPA: notifyDataSetChanged: fragment null, current item: %d", 364b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy currentItem); 365b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy } 36636280f3c2939bb2dacb4077bd528900346ff4bb9mindyp } else { 367631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal // notify unaffected fragment items of the change, so they can re-render 368631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal // (the change may have been to the labels for a single conversation, for example) 369631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal final AbstractConversationViewFragment frag = (cursor == null) ? null : 37026d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp (AbstractConversationViewFragment) getFragmentAt(pos); 3719d3fd92ed6091dbd0d38799222a1cf841f1c3f29Andy Huang if (frag != null && cursor.moveToPosition(pos) && frag.isUserVisible()) { 37216982472f8431aecfdb5f32aa7a97dce9064ac22mindyp // reload what we think is in the current position. 373631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal final Conversation conv = new Conversation(cursor); 374a825aae102a6112a0b4395eb3c5417c7b0c24262mindyp conv.position = pos; 375b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp frag.onConversationUpdated(conv); 376b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp mController.setCurrentConversation(conv); 37716982472f8431aecfdb5f32aa7a97dce9064ac22mindyp } 3781ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 379d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } else { 380d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "in CPA.notifyDataSetChanged, doing nothing. this=%s", this); 3811ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3821ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 383632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.notifyDataSetChanged(); 384d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang mInDataSetChange = false; 385632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 386632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 387632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 388632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setItemVisible(Fragment item, boolean visible) { 389632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.setItemVisible(item, visible); 390f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item; 391632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang fragment.setExtraUserVisibleHint(visible); 392632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 393632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 3941ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private Conversation getDefaultConversation() { 3951ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Conversation c = (mController != null) ? mController.getCurrentConversation() : null; 3961ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (c == null) { 3971ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang c = mInitialConversation; 3981ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3991ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return c; 4001ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 4011ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 402632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getConversationPosition(Conversation conv) { 403d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (conv == null) { 404d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang return POSITION_NONE; 405d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 406d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang 4075440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final ConversationCursor cursor = getCursor(); 4085440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 409d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang final Conversation def = getDefaultConversation(); 410d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (!conv.equals(def)) { 411d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "unable to find conversation in singleton mode. c=%s def=%s", 412d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang conv, def); 413632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return POSITION_NONE; 414632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 415d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "in CPA.getConversationPosition returning 0, conv=%s this=%s", 416d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang conv, this); 417632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return 0; 418632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 419632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 4205440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal // cursor is guaranteed to be non-null because isPagingDisabled() above checks for null 4215440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal // cursor. 422e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 423ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang int result = POSITION_NONE; 424c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook final int pos = cursor.getConversationPosition(conv.id); 425c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook if (pos >= 0) { 4269e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang LogUtils.d(LOG_TAG, "pager adapter found repositioned convo %s at pos=%d", 4279e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang conv, pos); 428c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook result = pos; 429ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang } 430ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang 431d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "in CPA.getConversationPosition (normal), conv=%s pos=%s this=%s", 432d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang conv, result, this); 433ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang return result; 434632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 435632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 43622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang public void setPager(ViewPager pager) { 4377d64612104fd861474a09994f13768360f92041dAndy Huang if (mPager != null) { 4387d64612104fd861474a09994f13768360f92041dAndy Huang mPager.setOnPageChangeListener(null); 4397d64612104fd861474a09994f13768360f92041dAndy Huang } 44022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang mPager = pager; 4417d64612104fd861474a09994f13768360f92041dAndy Huang if (mPager != null) { 4427d64612104fd861474a09994f13768360f92041dAndy Huang mPager.setOnPageChangeListener(this); 4437d64612104fd861474a09994f13768360f92041dAndy Huang } 44422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang } 44522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang 446090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang public void setActivityController(ActivityController controller) { 447d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang boolean wasNull = (mController == null); 4482821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null && !mStopListeningMode) { 449090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController.unregisterConversationListObserver(mListObserver); 450860164409d7f9e4f726ed4edb2ed77afc6873ad5Andy Huang mController.unregisterFolderObserver(mFolderObserver); 451632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 452090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController = controller; 4532821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null && !mStopListeningMode) { 454090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController.registerConversationListObserver(mListObserver); 45550ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal mFolderObserver.initialize(mController); 456d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang if (!wasNull) { 457d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang notifyDataSetChanged(); 458d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang } 459632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } else { 460e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang // We're being torn down; do not notify. 461e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang // Let the pager controller manage pager lifecycle. 462632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 463632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 464632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 4652821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang /** 4662821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * See {@link ConversationPagerController#stopListening()}. 4672821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang */ 4682821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang public void stopListening() { 469647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang if (mStopListeningMode) { 470647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang // Do nothing since we're already in stop listening mode. This avoids repeated 471647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang // unregister observer calls. 472647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang return; 473647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang } 474647aefbb36d4541362495e10e2a328d38ff8d2a2Alice Yang 4752821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang // disable the observer, but save off the current count, in case the Pager asks for it 4762821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang // from now until imminent destruction 4772821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 4782821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null) { 4792821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mController.unregisterConversationListObserver(mListObserver); 48050ff0e50f1a27144e55e4184f48e433439727e7bVikram Aggarwal mFolderObserver.unregisterAndDestroy(); 4812821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 4822821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mLastKnownCount = getCount(); 4836b81f0c6ac2061edd56ddb620fbbb4e04161f9d1Andy Huang mStopListeningMode = true; 484d6ce2fef197dce0f294e5565d9753aac894979dbAndy Huang LogUtils.d(LOG_TAG, "CPA.stopListening, this=%s", this); 4852821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 4862821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 4877d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4887d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 4897d64612104fd861474a09994f13768360f92041dAndy Huang // no-op 4907d64612104fd861474a09994f13768360f92041dAndy Huang } 4917d64612104fd861474a09994f13768360f92041dAndy Huang 4927d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4937d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageSelected(int position) { 49466db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal if (mController == null) { 49566db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal return; 49666db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal } 49766db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal final Cursor cursor = getCursor(); 49866db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal if (cursor == null || !cursor.moveToPosition(position)) { 49966db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal // No valid cursor or it doesn't have the position we want. Bail. 50066db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal return; 5017d64612104fd861474a09994f13768360f92041dAndy Huang } 50266db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal final Conversation c = new Conversation(cursor); 50366db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal c.position = position; 5049e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang LogUtils.d(LOG_TAG, "pager adapter setting current conv: %s", c); 50566db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal mController.setCurrentConversation(c); 5067d64612104fd861474a09994f13768360f92041dAndy Huang } 5077d64612104fd861474a09994f13768360f92041dAndy Huang 5087d64612104fd861474a09994f13768360f92041dAndy Huang @Override 5097d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageScrollStateChanged(int state) { 5107d64612104fd861474a09994f13768360f92041dAndy Huang // no-op 5117d64612104fd861474a09994f13768360f92041dAndy Huang } 5127d64612104fd861474a09994f13768360f92041dAndy Huang 513632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // update the pager dataset as the Controller's cursor changes 514632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private class ListObserver extends DataSetObserver { 515632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 516632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void onChanged() { 517e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang notifyDataSetChanged(); 518632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 519632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 520632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void onInvalidated() { 521632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 522632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 523632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 524632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang} 525