17a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal/******************************************************************************* 27a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * Copyright (C) 2012 Google Inc. 37a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * Licensed to The Android Open Source Project. 47a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * 57a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * Licensed under the Apache License, Version 2.0 (the "License"); 67a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * you may not use this file except in compliance with the License. 77a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * You may obtain a copy of the License at 87a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * 97a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * http://www.apache.org/licenses/LICENSE-2.0 107a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * 117a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * Unless required by applicable law or agreed to in writing, software 127a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * distributed under the License is distributed on an "AS IS" BASIS, 137a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 147a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * See the License for the specific language governing permissions and 157a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * limitations under the License. 167a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *******************************************************************************/ 177a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 187a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalpackage com.android.mail.providers; 197a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 207a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.app.LoaderManager; 217a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.content.Loader; 227a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.net.Uri; 237a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.os.Bundle; 2416027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sappersteinimport android.support.annotation.NonNull; 257a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 2677ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwalimport com.android.mail.content.ObjectCursor; 2777ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwalimport com.android.mail.content.ObjectCursorLoader; 287a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport com.android.mail.ui.AbstractActivityController; 297a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport com.android.mail.ui.RestrictedActivity; 307a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport com.android.mail.utils.LogUtils; 316bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrookimport com.google.common.collect.Lists; 327a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 337a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.ArrayList; 346bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrookimport java.util.Collections; 357a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.HashMap; 367a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.List; 377a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.Map; 387a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 397a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal/** 407a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * A container to keep a list of Folder objects, with the ability to automatically keep in sync with 417a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * the folders in the providers. 427a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */ 43d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwalpublic class FolderWatcher { 44de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal public static final String FOLDER_URI = "FOLDER-URI"; 457a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal /** List of URIs that are watched. */ 462b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal private final List<Uri> mUris = new ArrayList<Uri>(); 4777ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal /** Map returning the default inbox folder for each URI */ 484c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler private final Map<Uri, Folder> mInboxMap = new HashMap<Uri, Folder>(); 497a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal private final RestrictedActivity mActivity; 50d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal /** Handles folder callbacks and reads unread counts. */ 51d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal private final UnreadLoads mUnreadCallback = new UnreadLoads(); 52d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal 531dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal /** 541dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal * The adapter that consumes this data. We use this only to notify the consumer that new data 551dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal * is available. 561dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal */ 5716027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein private UnreadCountChangedListener mConsumer; 587a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 597a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal private final static String LOG_TAG = LogUtils.TAG; 607a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 6116027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein public static interface UnreadCountChangedListener { 6216027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein void onUnreadCountChange(); 6316027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein } 6416027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein 657a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal /** 667a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * Create a {@link FolderWatcher}. 67de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @param activity Upstream activity 6816027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein * @param listener A listener to be notified when the unread count changes 697a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */ 7016027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein public FolderWatcher( 7116027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein RestrictedActivity activity, @NonNull UnreadCountChangedListener listener) { 727a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal mActivity = activity; 7316027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein mConsumer = listener; 747a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 757a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 767a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal /** 77de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * Start watching all the accounts in this list and stop watching accounts NOT on this list. 78de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * Does nothing if the list of all accounts is null. 79de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @param allAccounts all the current accounts on the device. 807a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */ 81de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal public void updateAccountList(Account[] allAccounts) { 82de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal if (allAccounts == null) { 837a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal return; 847a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 85de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal // Create list of Inbox URIs from the array of accounts. 86de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal final List<Uri> newAccounts = new ArrayList<Uri>(allAccounts.length); 87de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal for (final Account account : allAccounts) { 88de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal newAccounts.add(account.settings.defaultInbox); 89de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 90de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal // Stop watching accounts not in the new list. 916bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrook final List<Uri> uriCopy = Collections.unmodifiableList(Lists.newArrayList(mUris)); 926bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrook for (final Uri previous : uriCopy) { 93de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal if (!newAccounts.contains(previous)) { 94de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal stopWatching(previous); 95de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 96de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 97de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal // Add accounts in the new list, that are not already watched. 98de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal for (final Uri fresh : newAccounts) { 992b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal if (!mUris.contains(fresh)) { 100de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal startWatching(fresh); 101de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 102de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 103de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 104de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal 105de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal /** 106de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * Starts watching the given URI for changes. It is NOT safe to call this method repeatedly 107de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * for the same URI. 108de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @param uri the URI for an inbox whose unread count is to be watched 109de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal */ 110de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal private void startWatching(Uri uri) { 111de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal final int location = insertAtNextEmptyLocation(uri); 112de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal LogUtils.d(LOG_TAG, "Watching %s, at position %d.", uri, location); 11377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal // No inbox folder yet, put a safe placeholder for now. 1144c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler mInboxMap.put(uri, null); 1157a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal final LoaderManager lm = mActivity.getLoaderManager(); 116de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal final Bundle args = new Bundle(); 117de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal args.putString(FOLDER_URI, uri.toString()); 118de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal lm.initLoader(getLoaderFromPosition(location), args, mUnreadCallback); 1197a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 1207a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 1217a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal /** 1222b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal * Locates the next empty position in {@link #mUris} and inserts the URI there, returning the 123de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * location. 124de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @return location where the URI was inserted. 1257a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */ 126de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal private int insertAtNextEmptyLocation(Uri newElement) { 127de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal Uri uri; 128de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal int location = -1; 1292b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal for (int size = mUris.size(), i = 0; i < size; i++) { 1302b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal uri = mUris.get(i); 131de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal // Hole in the list, use this position 132de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal if (uri == null) { 133de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal location = i; 134de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal break; 135de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 136de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 1370848874dababf76873290985168e9bf3d51d9c5dScott Kennedy 138de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal if (location < 0) { 1390848874dababf76873290985168e9bf3d51d9c5dScott Kennedy // No hole found, return the current size; 1402b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal location = mUris.size(); 1410848874dababf76873290985168e9bf3d51d9c5dScott Kennedy mUris.add(location, newElement); 1420848874dababf76873290985168e9bf3d51d9c5dScott Kennedy } else { 1430848874dababf76873290985168e9bf3d51d9c5dScott Kennedy mUris.set(location, newElement); 144de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal } 145de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal return location; 1467a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 1477a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 1487a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal /** 1492b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal * Returns the loader ID for a position inside the {@link #mUris} table. 1502b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal * @param position position in the {@link #mUris} list 151de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @return a loader id 1527a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */ 153de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal private static int getLoaderFromPosition(int position) { 154de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal return position + AbstractActivityController.LAST_LOADER_ID; 1557a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 1567a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 1577a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal /** 158d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal * Stops watching the given URI for folder changes. Subsequent calls to 159de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * {@link #getUnreadCount(Account)} for this uri will return null. 160de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @param uri the URI for a folder 1617a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */ 162de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal private void stopWatching(Uri uri) { 1630848874dababf76873290985168e9bf3d51d9c5dScott Kennedy if (uri == null) { 1640848874dababf76873290985168e9bf3d51d9c5dScott Kennedy return; 1650848874dababf76873290985168e9bf3d51d9c5dScott Kennedy } 1660848874dababf76873290985168e9bf3d51d9c5dScott Kennedy 1672b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal final int id = mUris.indexOf(uri); 168de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal // Does not exist in the list, we have stopped watching it already. 1697a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal if (id < 0) { 1707a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal return; 1717a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 1727a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal // Destroy the loader before removing references to the object. 1737a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal final LoaderManager lm = mActivity.getLoaderManager(); 1747a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal lm.destroyLoader(getLoaderFromPosition(id)); 1754c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler mInboxMap.remove(uri); 1760848874dababf76873290985168e9bf3d51d9c5dScott Kennedy mUris.set(id, null); 1777a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 1787a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 1797a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal /** 180de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * Returns the unread count for the default inbox for the account given. The account must be 181de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * watched with {@link #updateAccountList(Account[])}. If the account was not in an account 182de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * list passed previously, this method returns zero. 183de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @param account an account whose unread count we wisht to track 184de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * @return the unread count if the account was in array passed previously to {@link 185de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal * #updateAccountList(Account[])}. Zero otherwise. 1867a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */ 187de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal public final int getUnreadCount(Account account) { 18877ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal final Folder f = getDefaultInbox(account); 18977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal if (f != null) { 19077ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal return f.unreadCount; 19177ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal } 19277ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal return 0; 19377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal } 19477ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal 19577ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal public final Folder getDefaultInbox(Account account) { 196de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal final Uri uri = account.settings.defaultInbox; 1974c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler if (mInboxMap.containsKey(uri)) { 1984c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler final Folder candidate = mInboxMap.get(uri); 19977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal if (candidate != null) { 20077ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal return candidate; 201d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal } 202d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal } 20377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal return null; 2047a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 2057a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 206d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal /** 207d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal * Class to perform {@link LoaderManager.LoaderCallbacks} for populating unread counts. 208d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal */ 20977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal private class UnreadLoads implements LoaderManager.LoaderCallbacks<ObjectCursor<Folder>> { 210d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal // TODO(viki): Fix http://b/8494129 and read only the URI and unread count. 211b789b03fbedfb4fbaa0fb980725fbcd3e1d8d851Vikram Aggarwal /** Only interested in the folder unread count, but asking for everything due to 212b789b03fbedfb4fbaa0fb980725fbcd3e1d8d851Vikram Aggarwal * bug 8494129. */ 213de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal private final String[] projection = UIProvider.FOLDERS_PROJECTION; 214de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal 215d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal @Override 21677ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal public Loader<ObjectCursor<Folder>> onCreateLoader(int id, Bundle args) { 217de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal final Uri uri = Uri.parse(args.getString(FOLDER_URI)); 21877ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal return new ObjectCursorLoader<Folder>(mActivity.getActivityContext(), uri, projection, 21977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal Folder.FACTORY); 2207a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 2217a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 222d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal @Override 22377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal public void onLoadFinished(Loader<ObjectCursor<Folder>> loader, ObjectCursor<Folder> data) { 224d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal if (data == null || data.getCount() <= 0 || !data.moveToFirst()) { 225d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal return; 226d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal } 22777ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal final Folder f = data.getModel(); 228cd686c1cd99379c6d3ab66ccbfd7f6ae4e4eb67bScott Kennedy final Uri uri = f.folderUri.getComparisonUri(); 22977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal final int unreadCount = f.unreadCount; 2304c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler final Folder previousFolder = mInboxMap.get(uri); 23177ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal final boolean unreadCountChanged = previousFolder == null 23277ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal || unreadCount != previousFolder.unreadCount; 2334c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler mInboxMap.put(uri, f); 234d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal // Once we have updated data, we notify the parent class that something new appeared. 23577ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal if (unreadCountChanged) { 23616027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein mConsumer.onUnreadCountChange(); 23721115dcf79619a8fd63378ba89c5944b1256a7abVikram Aggarwal } 2387a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 2397a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal 240d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal @Override 24177ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal public void onLoaderReset(Loader<ObjectCursor<Folder>> loader) { 242d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal // Do nothing. 243d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal } 2447a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal } 2457a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal} 246