1 /*
2  * Copyright (C) 2012 Google Inc.
3  * Licensed to The Android Open Source Project.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.mail.ui;
19 
20 import android.app.Activity;
21 import android.content.AsyncTaskLoader;
22 import android.net.Uri;
23 
24 import com.android.mail.browse.ConversationCursor;
25 import com.android.mail.providers.Account;
26 import com.android.mail.providers.UIProvider.AccountCapabilities;
27 import com.android.mail.utils.LogUtils;
28 
29 import java.util.ArrayList;
30 
31 public class ConversationCursorLoader extends AsyncTaskLoader<ConversationCursor> {
32     private static final String TAG = "ConversationCursorLoader";
33     private final Uri mUri;
34     private final ConversationCursor mConversationCursor;
35     private boolean mInit = false;
36     private boolean mClosed = false;
37     private boolean mRetain = false;
38     private boolean mRetained = false;
39     private final String mName;
40 
41     /** Only used for debugging. Turn {@link #DEBUG} on to make this useful. */
42     private static final boolean DEBUG = false;
43     private static final ArrayList<ConversationCursorLoader> sLoaders =
44             new ArrayList<ConversationCursorLoader>();
45 
ConversationCursorLoader(Activity activity, Account account, Uri uri, String name, boolean ignoreInitialConversationLimit)46     public ConversationCursorLoader(Activity activity, Account account,
47             Uri uri, String name, boolean ignoreInitialConversationLimit) {
48         super(activity);
49         mUri = uri;
50         mName = name;
51         final boolean useInitialConversationLimit = ignoreInitialConversationLimit ? false :
52                 account.supportsCapability(AccountCapabilities.INITIAL_CONVERSATION_LIMIT);
53         // Initialize the state of the conversation cursor
54         mConversationCursor = new ConversationCursor(
55                 activity, mUri, useInitialConversationLimit, name);
56         addLoader();
57     }
58 
dumpLoaders()59     private static void dumpLoaders() {
60         if (DEBUG) {
61             LogUtils.d(TAG, "Loaders: ");
62             for (ConversationCursorLoader loader: sLoaders) {
63                 LogUtils.d(TAG, " >> " + loader.mName + " (" + loader.mUri + ")");
64             }
65         }
66     }
67 
addLoader()68     private void addLoader() {
69         if (DEBUG) {
70             LogUtils.d(TAG, "Add loader: " + mUri);
71             sLoaders.add(this);
72             if (sLoaders.size() > 1) {
73                 dumpLoaders();
74             }
75         }
76     }
77 
78     /**
79      * Indicate whether the loader's cursor should be retained after reset
80      * @param state whether this laoder's cursor should be retained
81      */
retainCursor(boolean state)82     public void retainCursor(boolean state) {
83         mRetain = state;
84     }
85 
86     @Override
onReset()87     public void onReset() {
88         if (!mRetain) {
89             // Mark the cursor as disabled
90             mConversationCursor.disable();
91             mClosed = true;
92             if (DEBUG) {
93                 LogUtils.d(TAG, "Reset loader/disable cursor: " + mName);
94                 sLoaders.remove(this);
95                 if (!sLoaders.isEmpty()) {
96                     dumpLoaders();
97                 }
98             }
99         } else {
100             if (DEBUG) {
101                 LogUtils.d(TAG, "Reset loader/retain cursor: " + mName);
102                 mRetained = true;
103             }
104         }
105     }
106 
107     @Override
loadInBackground()108     public ConversationCursor loadInBackground() {
109         if (!mInit) {
110             mConversationCursor.load();
111             mInit = true;
112         }
113         return mConversationCursor;
114     }
115 
116     @Override
onStartLoading()117     protected void onStartLoading() {
118         if (mClosed) {
119             mClosed = false;
120             mConversationCursor.load();
121             addLoader();
122             if (DEBUG) {
123                 LogUtils.d(TAG, "Restarting reset loader: " + mName);
124             }
125         } else if (mRetained) {
126             mRetained = false;
127             if (DEBUG) {
128                 LogUtils.d(TAG, "Resuming retained loader: " + mName);
129             }
130         }
131         forceLoad();
132         mConversationCursor.resume();
133     }
134 
135     @Override
onStopLoading()136     protected void onStopLoading() {
137         cancelLoad();
138         mConversationCursor.pause();
139     }
140 }
141