Wait for AsyncTask to complete using ProgressDialog

I have a public void writeEntry(Activity ctx, Entry entry) method that gets some data and needs to call its own method, which takes longer. So I created AsyncTask, which processes the ProgressDialog and its own method. It works great in its own activities to test it, in this event I used the callback interface, etc.

In my case, I have the method described above and you have to execute AsyncTask. Execution cannot be in this method because it does not stop further execution.
I need a result from my own method before I can continue execution.
Is it possible to wait for AsyncTask to complete? The wait() method is not an option because the UI thread will also wait, and therefore the meaning of ProgressDialog will be lost.

Can I use the runOnUiThread() method from the given parameters or is it the only solution to start my own action?

+4
source share
2 answers

My first solution was to use callback methods with an interface implementation in the fooobar.com/questions/1358363 / ... example.

After chatting on Android chat, I heard that there is a more important solution.
You can use IntentService in combination with PendingIntent.
Communication is done using Intent's.
If you want to use the ProgressDialog, for this you need your own action, which registers, for example, BroadcastReciever, and the IntentService sends its actual status for the broadcast.

But let's get started now. First we create an Activity that contains a ProgressDialog and a registered BroadcastReceiver. BroadcastReceiver listens for update and completion messages.

For Activity, we need a layout ...

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#80000000"> </LinearLayout> 

... and related code:

 public class ProgressActivity extends Activity { /** * ProgressDialog which is shown */ private ProgressDialog progessDialog_g; /** * Instance of the BroadcastReceiver */ private BroadcastReceiver receiver_g; /** * Identifier for the different settings of the ProgressDialog */ public static final String PROGRESS_DIALOG_BOOL_HORIZONTAL_BAR = "pbar_horizontal_bar"; public static final String PROGRESS_DIALOG_BOOL_CANCELABLE = "pbar_horizontal_cancelable"; public static final String PROGRESS_DIALOG_STR_MESSAGE = "pbar_message"; public static final String PROGRESS_DIALOG_INT_MAX = "pbar_max_bar"; public static final String PROGRESS_DIALOG_INT_VALUE = "pbar_value"; protected static final int PROGRESS_DIALOG_INT_MAX_VALUE = 100; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.progress); progessDialog_g = new ProgressDialog(this); // Reads and sets the settings for the ProgressDialog Intent i = getIntent(); progessDialog_g.setCancelable(i.getBooleanExtra( PROGRESS_DIALOG_BOOL_CANCELABLE, false)); if (i.getBooleanExtra( PROGRESS_DIALOG_BOOL_HORIZONTAL_BAR, false)) { progessDialog_g.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); } else { progessDialog_g.setProgressStyle(ProgressDialog.STYLE_SPINNER); } progessDialog_g .setMessage(i .getStringExtra(PROGRESS_DIALOG_STR_MESSAGE)); progessDialog_g.setMax(i.getIntExtra( PROGRESS_DIALOG_INT_MAX, 100)); // Create the IntentFilter for the different broadcast messages IntentFilter iFilter = new IntentFilter( ExampleProgressService.PROGRESS_DIALOG_BROADCAST_INIT); iFilter.addAction(ExampleProgressService.PROGRESS_DIALOG_BROADCAST_UPDATE); iFilter.addAction(ExampleProgressService.PROGRESS_DIALOG_BROADCAST_FINISH); // Creates the BroadcastReceiver receiver_g = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent){ Log.d(DefaultPreferences.DEBUG_PREFIX + "ProgressActivity", intent.getAction()); if (ExampleProgressService.PROGRESS_DIALOG_BROADCAST_INIT .equals(intent.getAction())) { // Sets the ProgressDialog style if (intent .getBooleanExtra( PROGRESS_DIALOG_BOOL_HORIZONTAL_BAR, false)) { progessDialog_g .setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); } else { progessDialog_g .setProgressStyle(ProgressDialog.STYLE_SPINNER); } // Shows the ProgressDialog progessDialog_g.show(); } else if (ExampleProgressService.PROGRESS_DIALOG_BROADCAST_UPDATE .equals(intent.getAction())) { // Updates the ProgressDialog int value = intent.getIntExtra( PROGRESS_DIALOG_INT_VALUE, -1); if (value != -1) { progessDialog_g.setProgress(value); } } else if (ExampleProgressService.PROGRESS_DIALOG_BROADCAST_FINISH .equals(intent.getAction())) { // Finishs the ProgressDialog progessDialog_g.cancel(); finish(); } } }; // Registers the BroadcastReceiver registerReceiver(receiver_g, iFilter); } @Override protected void onDestroy(){ unregisterReceiver(receiver_g); super.onDestroy(); } } 

Now we want to use Activity, so let's start by calling it:

 final Intent i = new Intent(parentActivity, <packages>.ProgressActivity); i.putExtra(ProgressActivity.PROGRESS_DIALOG_BOOL_CANCELABLE, cancelable_g); i.putExtra(ProgressActivity.PROGRESS_DIALOG_BOOL_HORIZONTAL_BAR, showProgress_g); i.putExtra(ProgressActivity.PROGRESS_DIALOG_STR_MESSAGE, message_g); i.putExtra(ProgressActivity.PROGRESS_DIALOG_INT_MAX, ProgressActivity.PROGRESS_DIALOG_INT_MAX_VALUE); parentActivity.startActivity(i); 

Thus, we launch the current ProgressActivity, which is waiting for various transfers. But first, we need an IntentService that sends broadcasts.
So release:

 public class ExampleProgressService extends IntentService { /** * PendingIntent for callback. */ protected PendingIntent pi_g = null; private static final String DEBUG_TAG = "ExampleProgressService"; /** * Message identifier for ProgressDialog init */ public static final String PROGRESS_DIALOG_BROADCAST_INIT = "Dialog.Progress.Init"; /** * Message identifier for ProgressDialog finish */ public static final String PROGRESS_DIALOG_BROADCAST_FINISH = "Dialog.Progress.Finish"; /** * Message identifier for ProgressDialog update */ public static final String PROGRESS_DIALOG_BROADCAST_UPDATE = "Dialog.Progress.Update"; /** * Identifier of the result for intent content */ public static final String PROGRESS_DATA_RESULT = "Result"; /** * Identifier of the result error for intent content */ public static final String PROGRESS_DATA_RESULT_ERROR_MESSAGE = "Result.Error.Message"; /** * Identifier of the result error exception for intent content */ public static final String PROGRESS_DATA_RESULT_ERROR_EXCEPTION = "Result.Error.Exception"; /** * Identifier of the result status for intent content */ public static final String PROGRESS_DATA_RESULT_STATUS_BOOL = "Result.Status.boolean"; /** * Identifier of the pending intent for intent content */ public static final String PROGRESS_DATA_PENDING_RESULT = "PendingResult"; public ExampleProgressService() { super("ExampleProgressService"); } /** * Send the finish message. */ private void closeProgressActivity() { Intent intent = new Intent(PROGRESS_DIALOG_BROADCAST_FINISH); sendBroadcast(intent); } /** * Do some magic with the intent content */ private void extractVariablesFromIntentAndPrepare(Intent intent) throws Exception { pi_g = (PendingIntent) intent .getParcelableExtra(PROGRESS_DATA_PENDING_RESULT); if (pi_g == null) { throw new Exception("There is no pending intent!"); } /** * Sends an error message. */ private void failed(Exception e, String message) { Intent i = new Intent(); i.putExtra(PROGRESS_DATA_RESULT_ERROR_EXCEPTION, e); i.putExtra(PROGRESS_DATA_RESULT_ERROR_MESSAGE, message); send(i, false); } /** * Sends the init message. */ private void initProgressActivity() { Intent intent = new Intent(PROGRESS_DIALOG_BROADCAST_INIT); intent.putExtra(PROGRESS_DIALOG_BOOL_HORIZONTAL_BAR, multipart_g); sendBroadcast(intent); } /** * (non-Javadoc) * * @see android.app.IntentService#onHandleIntent(android.content.Intent) */ @Override protected void onHandleIntent(Intent intent) { extractVariablesFromIntentAndPrepare(intent); initProgressActivity(); // do your calculation here and implements following code Intent intent = new Intent(PROGRESS_DIALOG_BROADCAST_UPDATE); intent.putExtra(PROGRESS_DIALOG_INT_VALUE, progressValue); sendBroadcast(intent); // If you finished, use one of the two methods to send the result or an error success(result); failed(exception, optionalMessage); } /** * Sends the data to the calling Activity */ private void send(Intent resultData, boolean status) { resultData.putExtra(PROGRESS_DATA_RESULT_STATUS_BOOL, status); closeProgressActivity(); try { pi_g.send(this, Activity.RESULT_OK, resultData); } catch (PendingIntent.CanceledException e) { Log.e(DEBUG_TAG, "There is something wrong with the pending intent", e); } } /** * Sends the result message. */ private void success(String result) { Intent i = new Intent(); i.putExtra(PROGRESS_DATA_RESULT, result); send(i, true); } } 

The result of the calculation must be available in parentActivity , so we create a PendingIntent in this Activity and call the IntentService.

 // Some identifier for the call int requestCode = 12345; final Intent sI = new Intent(ExampleProgressService.PROGRESS_SERVICE_ACTION); // Callback sI.putExtra(ExampleProgressService.PROGRESS_DATA_PENDING_RESULT, parentActivity .createPendingResult(requestCode, null, PendingIntent.FLAG_CANCEL_CURRENT)); // Service start parentActivity.startService(sI); 

To get the results, we must override the onActivityResult(int requestCode, int resultCode, Intent data) method onActivityResult(int requestCode, int resultCode, Intent data) .

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ // Compares the requestCode with the requestCode from above if (requestCode == ...) { if (data.getBooleanExtra(ExampleProgressService.PROGRESS_DATA_RESULT_STATUS_BOOL, false)) { // Calculation was success data.getStringExtra(ExampleProgressService.PROGRESS_DATA_RESULT); } else { // Calculation is failed data.getStringExtra(ExampleProgressService.PROGRESS_DATA_RESULT_ERROR_MESSAGE); ((Exception) data.getSerializableExtra(ExampleProgressService.PROGRESS_DATA_RESULT_ERROR_EXCEPTION)); } } } 

It was magic, I hope this helps you.

+3
source

so I will try to explain as much as possible

Run your heavy process inside AsyncTask, but any code you want to execute after AsyncTask completes, put it in a separate public method. Now that you have finished your difficult process, call this separately created method in onPostExecute() .

So, the psuuedo code will look like this:

 class main extends Activity { class Something extends AsyncTask<String, Integer, String> { protected void onPreExecute() { // Start your progress bar... } protected String doInBackground(String... params) { // Do your heavy stuff... return null; } protected void onPostExecute(String result) { // close your progress dialog and than call method which has // code you are wishing to execute after AsyncTask. } } } 

Hope this helps,

Good luck

+4
source

All Articles