Home Android Tutorials Handling Long Running Operations In Google Android

Lastest Discussion

Handling Long Running Operations In Google Android PDF Print E-mail

User interface responsiveness is a crucial thing for all applications that require user interaction, but maybe even more so when programming for mobile handsets. Google’s Android programming environment unfortunately does not provide any mechanism for handling operations that may require a fair amount of time to complete, but which in itself are not meant to be implemented as Android Services. An example for this would be network I/O in an Activity, such as posting data to (or retrieving data from) a remote Web server. Because the Android runtime will terminate any Activity that does not respond within a couple of seconds, it is impossible (and simply a bad idea anyway) to perform such tasks from within the UI main thread.

That being said, I have come up with a generic class that handles long running operations by spawning a separate thread and passing back any result or error data to the main thread using a callback mechanism. An animated progress dialog will be displayed while the operation is running. That way the user is kept informed about any program activity that may take some time to complete.

The class can be used as follows:

 
  1. public class MyActivity implements LongRunningActionCallback<Void> { 
  2.  
  3.     private LongRunningActionDispatcher<Void> dispatcher; 
  4.  
  5.     private void startLongRunningOperation() { 
  6.         // the first argument is a reference to the current Context, in this 
  7.         // case the current Activity. The second argument is a reference to 
  8.         // the object implementing the callback method. 
  9.         this.dispatcher = new LongRunningActionDispatcher<Void>(this, this); 
  10.         dispatcher.startLongRunningAction(new Callable<Void>() { 
  11.             public Void call() throws Exception { 
  12.                 // perform your actions that take a long time 
  13.                 return null
  14.             } 
  15.         }, "Dialog Title", "Dialog message"); 
  16.     } 
  17.  
  18.     // the callback 
  19.     public void onLongRunningActionFinished(Void result, Exception error) { 
  20.         if (error != null) { 
  21.             // handle error 
  22.         } else
  23.             // success, work with the result, if any 
  24.         } 
  25.     } 

This will spawn a progress dialog (not indicating any actual progress in percentage, it’s just a “busy” dialog) with the given title and message. If an exception occurred in the Callable you provided, it will be passed as the error argument to the callback, so you should always check whether it’s non-null.

Below are the source codes for both LongRunningActionDispatcher and LongRunningActionCallback.

 
  1. import java.util.concurrent.Callable; 
  2.  
  3. import android.app.ProgressDialog; 
  4. import android.content.Context; 
  5. import android.os.Handler; 
  6. import android.util.Log; 
  7.  
  8. /**
  9.  * Use this class if you need to dispatch expensive (long running) operations
  10.  * from your Activity. The long running operation is provided to
  11.  * {@link startLongRunningAction} as a {@link Callable}. The result of the
  12.  * operation and any potential exception that occurred during the call are
  13.  * passed to {@link LongRunningActionCallback.onLongRunningActionFinished},
  14.  * which will be called on successful or unsuccessful completion of the
  15.  * Callable.
  16.  *
  17.  * LICENSE STATEMENT (DO NOT REMOVE):
  18.  * This code is in the public domain. You may use, alter, and redistribute it
  19.  * free of any charges or obligations, with the following exceptions:
  20.  * 1. You are not allowed to remove the statement naming the original author.
  21.  * 2. You are not allowed to remove this license statement.
  22.  *
  23.  * @author Matthias Kaeppler
  24.  */ 
  25. public final class LongRunningActionDispatcher<ResultType> { 
  26.  
  27.     private Context context; 
  28.  
  29.     private LongRunningActionCallback<ResultType> callback; 
  30.  
  31.     /**
  32.      * A progress dialog shown during long-lasting operations
  33.      */ 
  34.     private ProgressDialog progressDialog; 
  35.  
  36.     private Handler finishedHandler = new Handler(); 
  37.  
  38.     public LongRunningActionDispatcher(Context context, 
  39.             LongRunningActionCallback<ResultType> callback) { 
  40.         this.context = context; 
  41.         this.callback = callback; 
  42.     } 
  43.  
  44.     /**
  45.      * Invoke this method to start long running operations which may block your
  46.      * activity and therefore the main UI thread. A progress dialog will be
  47.      * shown while the operation is executing.
  48.      *
  49.      * @param callable
  50.      *            The callable
  51.      * @param progressDialogTitle
  52.      *            The progress dialog title
  53.      * @param progressDialogMessage
  54.      *            The progress dialog message
  55.      */ 
  56.     public void startLongRunningAction(final Callable<ResultType> callable, 
  57.             String progressDialogTitle, String progressDialogMessage) { 
  58.  
  59.         progressDialog = ProgressDialog.show(context, progressDialogTitle, 
  60.                 progressDialogMessage, true, false); 
  61.  
  62.         new Thread(new Runnable() { 
  63.  
  64.             public void run() { 
  65.                 ResultType result = null
  66.                 Exception error = null
  67.                 try
  68.                     result = callable.call(); 
  69.                 } catch (Exception e) { 
  70.                     Log.e("ERROR", e.getMessage()); 
  71.                     error = e; 
  72.                 } 
  73.  
  74.                 final ResultType finalResult = result; 
  75.                 final Exception finalError = error; 
  76.                 finishedHandler.post(new Runnable() { 
  77.  
  78.                     public void run() { 
  79.                         onLongRunningActionFinished(finalResult, finalError); 
  80.                     } 
  81.                 }); 
  82.             } 
  83.         }).start(); 
  84.     } 
  85.  
  86.     private void onLongRunningActionFinished(ResultType result, Exception error) { 
  87.         progressDialog.dismiss(); 
  88.         callback.onLongRunningActionFinished(result, error); 
  89.     } 
 
  1. /**
  2.  * LICENSE STATEMENT (DO NOT REMOVE):
  3.  * This code is in the public domain. You may use, alter, and redistribute it
  4.  * free of any charges or obligations, with the following exceptions:
  5.  * 1. You are not allowed to remove the statement naming the original author.
  6.  * 2. You are not allowed to remove this license statement.
  7.  *
  8.  * @author Matthias Kaeppler
  9.  */ 
  10. public interface LongRunningActionCallback<ResultType> { 
  11.  
  12.     /**
  13.      * Called when the callable provided to
  14.      * {@link LongRunningActionDispatcher.startLongRunningAction} completes.
  15.      *
  16.      * @param <ResultType>
  17.      *            The result type of callable.call()
  18.      * @param result
  19.      *            Whatever the callable returns if it completes successfully, or
  20.      *            null if an exception was thrown
  21.      * @param error
  22.      *            Whatever the callable throws if it executes in error, or null
  23.      *            if it completed successfully
  24.      */ 
  25.     void onLongRunningActionFinished(ResultType result, Exception error); 
 

Taken from brainflush blog

Bookmark with:

Deli.cio.us    Digg    reddit    Facebook    StumbleUpon    Newsvine
Comments (0)
Only registered users can write comments!