Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/bookmark/AsyncTaskFragment.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.bookmark;
6
7 import android.app.Activity;
8 import android.app.Fragment;
9 import android.app.ProgressDialog;
10 import android.os.AsyncTask;
11 import android.os.Bundle;
12 import android.os.Handler;
13
14 /**
15 * Fragment that allows running asynchronous tasks showing a progress dialog if it takes too long.
16 * Since each task blocks the UI in an informative way, only one task is allowed at once.
17 * The fragment is retained in order to correctly support screen rotation change s and to prevent
18 * tasks to run multiple times. Tasks are automatically canceled if the fragment is destroyed.
19 * This class assumes that all its public methods will be called from the UI thr ead.
20 *
21 * The main purpose of this class is to allow fragments to correcly use our prov ider considering
22 * that it should never been called from the UI thread.
23 */
24 public class AsyncTaskFragment extends Fragment {
25 /**
26 * Delay in milliseconds introduced before showing the progress dialog.
27 * Introduced in order to avoid flickering for short operations.
28 */
29 private static final int DELAY_BEFORE_PROGRESS_DIALOG_MS = 300;
30
31 /**
32 * Minimum time in miliseconds the dialog stays if shown.
33 * This will artificially delay the result of the asynchronous tasks.
34 * Will be ignored if the task is cancelled.
35 */
36 private static final int MINIMUM_DIALOG_STAY_MS = 500;
37
38 private final Handler mHandler = new Handler();
39 private ProgressDialog mProgressDialog;
40 private String mDialogMessage;
41 private boolean mShouldShowDialog;
42 private boolean mHasDialogStayedEnough;
43 protected FragmentAsyncTask mCurrentTask;
44
45 private final Runnable mShowProgressDialog = new Runnable() {
46 @Override
47 public void run() {
48 mShouldShowDialog = true;
49 showDialog();
50 }
51 };
52
53 private final Runnable mDialogStaysEnough = new Runnable() {
54 @Override
55 public void run() {
56 mHasDialogStayedEnough = true;
57 if (mCurrentTask != null) mCurrentTask.onDialogStayedEnough();
58 }
59 };
60
61 /**
62 * @return true if an asynchronous fragment task is currently running in the fragment.
63 */
64 public boolean isFragmentAsyncTaskRunning() {
65 return mCurrentTask != null;
66 }
67
68 /**
69 * Starts a new asynchronous fragment task. Will fail if another task is alr eady running.
70 *
71 * @param task New asynchronous fragment task to run.
72 * @param dialogMessage Message shown in the progress dialog while the task is run.
73 */
74 public boolean runFragmentAsyncTask(FragmentAsyncTask task, String dialogMes sage) {
75 if (isFragmentAsyncTaskRunning() || task == null) return false;
76
77 mCurrentTask = task;
78 mDialogMessage = dialogMessage;
79 mShouldShowDialog = false;
80 mHasDialogStayedEnough = false;
81 mHandler.postDelayed(mShowProgressDialog, DELAY_BEFORE_PROGRESS_DIALOG_M S);
82 task.execute();
83 return true;
84 }
85
86 /**
87 * Cancels the execution of any ongoing fragment asynchronous task.
88 * Note that this doesn't ensure the immediate interruption of the task.
89 */
90 public void cancelFragmentAsyncTask() {
91 if (mCurrentTask != null) {
92 mCurrentTask.cancel(false);
93 taskFinished();
94 }
95 }
96
97 /**
98 * Base class for asynchronous tasks to be run within the fragment.
99 */
100 public abstract class FragmentAsyncTask extends AsyncTask<Void, Void, Void> {
101 /**
102 * Method called to run the asynchronous code.
103 */
104 protected abstract void runBackgroundTask();
105
106 /**
107 * Method called when the asynchronous task has finished.
108 */
109 protected abstract void onTaskFinished();
110
111 /**
112 * Method called to disable the UI elements that depend on the task when it starts,
113 * and again to re-enable them when finished or cancelled.
114 */
115 protected abstract void setDependentUIEnabled(boolean enabled);
116
117 /**
118 * Updates the enabled status of the UI elements depending on the task a ccording to
119 * the current task status.
120 */
121 public void updateDependentUI() {
122 setDependentUIEnabled(getStatus() != Status.RUNNING);
123 }
124
125 @Override
126 protected void onPreExecute() {
127 setDependentUIEnabled(false);
128 }
129
130 @Override
131 protected Void doInBackground(Void... params) {
132 runBackgroundTask();
133 return null;
134 }
135
136 @Override
137 protected void onPostExecute(Void result) {
138 // Don't dispatch the task result yet if the dialog is present and h asn't stayed enough.
139 if (mProgressDialog == null || mHasDialogStayedEnough) finishTask();
140 }
141
142 @Override
143 protected void onCancelled(Void result) {
144 cleanUp();
145 }
146
147 private void finishTask() {
148 cleanUp();
149 onTaskFinished();
150 }
151
152 private void cleanUp() {
153 setDependentUIEnabled(true);
154 taskFinished();
155 }
156
157 void onDialogStayedEnough() {
158 // Dispatch the results of any finished tasks that are waiting for t he dialog.
159 if (getStatus() == Status.FINISHED) finishTask();
160 }
161 }
162
163 @Override
164 public void onAttach(Activity activity) {
165 super.onAttach(activity);
166 showDialog();
167 }
168
169 @Override
170 public void onDetach() {
171 super.onDetach();
172 hideDialog();
173 }
174
175 @Override
176 public void onCreate(Bundle savedInstanceState) {
177 super.onCreate(savedInstanceState);
178 super.setRetainInstance(true);
179 }
180
181 @Override
182 public void onDestroy() {
183 super.onDestroy();
184 cancelFragmentAsyncTask();
185 }
186
187 @Override
188 public void onActivityCreated(Bundle savedInstanceState) {
189 super.onActivityCreated(savedInstanceState);
190 if (isFragmentAsyncTaskRunning()) updateTaskDependentUI();
191 }
192
193 @Override
194 public void onHiddenChanged(boolean hidden) {
195 super.onHiddenChanged(hidden);
196 if (hidden) {
197 hideDialog();
198 } else {
199 showDialog();
200 }
201 }
202
203 @Override
204 public void setRetainInstance(boolean retain) {
205 // The fragment is always retained for task and dialog consistence when rotating the screen.
206 assert retain;
207 }
208
209 private void updateTaskDependentUI() {
210 if (mCurrentTask != null) mCurrentTask.updateDependentUI();
211 }
212
213 private void showDialog() {
214 if (isDetached() || isHidden() || !mShouldShowDialog) return;
215 mProgressDialog = ProgressDialog.show(getActivity(), null, mDialogMessag e, true, false);
216 mHandler.postDelayed(mDialogStaysEnough, MINIMUM_DIALOG_STAY_MS);
217 }
218
219 private void hideDialog() {
220 if (mProgressDialog != null) {
221 mProgressDialog.dismiss();
222 mProgressDialog = null;
223 }
224 }
225
226 private void taskFinished() {
227 mHandler.removeCallbacks(mShowProgressDialog);
228 mHandler.removeCallbacks(mDialogStaysEnough);
229 hideDialog();
230 mShouldShowDialog = false;
231 mHasDialogStayedEnough = false;
232 mCurrentTask = null;
233 }
234 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698