/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.mms.ui; import android.app.Activity; import android.app.ProgressDialog; import android.os.AsyncTask; import android.os.Handler; /** * This AsyncDialog class is used to execute a runnable in a background thread and once that * finishes, execute a runnable on the UI thread. If the background runnable task takes longer * than half a second, a progress modal dialog is displayed. * */ public class AsyncDialog { private ProgressDialog mProgressDialog; private final Activity mActivity; private final Handler mHandler; public AsyncDialog(Activity activity) { mActivity = activity; mHandler = new Handler(); } /** * Asynchronously executes a task while blocking the UI with a progress spinner. * * Must be invoked by the UI thread. No exceptions! * * @param backgroundTask the work to be done in the background wrapped in a Runnable * @param postExecuteTask an optional runnable to run on the UI thread when the background * runnable is finished * @param dialogStringId the id of the string to be shown in the dialog */ public void runAsync(final Runnable backgroundTask, final Runnable postExecuteTask, final int dialogStringId) { new ModalDialogAsyncTask(dialogStringId, postExecuteTask) .execute(new Runnable[] {backgroundTask}); } // Shows the activity's progress spinner. Should be canceled if exiting the activity. private Runnable mShowProgressDialogRunnable = new Runnable() { @Override public void run() { if (mProgressDialog != null) { mProgressDialog.show(); } } }; public void clearPendingProgressDialog() { // remove any callback to display a progress spinner mHandler.removeCallbacks(mShowProgressDialogRunnable); // clear the dialog so any pending dialog.dismiss() call can be avoided mProgressDialog = null; } /** * Asynchronously performs tasks specified by Runnables. * Displays a progress spinner while the tasks are running. The progress spinner * will only show if tasks have not finished after a certain amount of time. * * This AsyncTask must be instantiated and invoked on the UI thread. * * TODO: Need to implement a way for the background thread to pass a result to * the onPostExecute thread. AsyncTask already provides this functionality. */ private class ModalDialogAsyncTask extends AsyncTask<Runnable, Void, Void> { final Runnable mPostExecuteTask; /** * Creates the Task with the specified string id to be shown in the dialog */ public ModalDialogAsyncTask(int dialogStringId, final Runnable postExecuteTask) { mPostExecuteTask = postExecuteTask; // lazy initialization of progress dialog for loading attachments if (mProgressDialog == null) { mProgressDialog = createProgressDialog(); } mProgressDialog.setMessage(mActivity.getText(dialogStringId)); } /** * Initializes the progress dialog with its intended settings. */ private ProgressDialog createProgressDialog() { ProgressDialog dialog = new ProgressDialog(mActivity); dialog.setIndeterminate(true); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); return dialog; } /** * Activates a progress spinner on the UI. This assumes the UI has invoked this Task. */ @Override protected void onPreExecute() { // activate spinner after half a second mHandler.postDelayed(mShowProgressDialogRunnable, 500); } /** * Perform the specified Runnable tasks on a background thread */ @Override protected Void doInBackground(Runnable... params) { if (params != null) { try { for (int i = 0; i < params.length; i++) { params[i].run(); } // Test code. Uncomment this block to test the progress dialog popping up. // try { // Thread.sleep(2000); // } catch (Exception e) { // } } finally { // Cancel pending display of the progress bar if the background task has // finished before the progress bar has popped up. mHandler.removeCallbacks(mShowProgressDialogRunnable); } } return null; } /** * Deactivates the progress spinner on the UI. This assumes the UI has invoked this Task. */ @Override protected void onPostExecute(Void result) { if (mActivity.isFinishing()) { return; } if (mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); } if (mPostExecuteTask != null) { mPostExecuteTask.run(); } } } }