Дождитесь выполнения AsyncTask с ProgressDialog
У меня есть метод public void writeEntry(Activity ctx, Entry entry)
, который получает некоторые данные и должен вызывать собственный метод, который занимает больше времени для завершения.
Поэтому я создал AsyncTask , который обрабатывает ProgressDialog и собственный метод. Он отлично работает в собственном действии, чтобы проверить его, в этом действии я использовал интерфейс обратного вызова и так далее.
В моем случае я использую вышеописанный метод и должен выполнитьAsyncTask . Выполнение не может быть в этом методе, потому что он не останавливает дальнейшую казнь.
Мне нужен результат от собственного метода, прежде чем я смогу продолжить выполнение.
Есть ли возможность дождаться AsyncTask , пока он не будет завершен? Метод wait()
не является опцией, потому что поток пользовательского интерфейса тоже будет ждать, и поэтому смыслProgressDialog будет потерян.
Могу ли я использовать метод runOnUiThread()
из заданных параметров или это единственное решение, чтобы начать собственную деятельность ?
2 ответа:
Поэтому я постараюсь объяснить как можно больше
Начните свой тяжелый процесс внутри AsyncTask, но любой код, который вы хотите выполнить после завершения AsyncTask, поместите его в отдельный открытый метод. Теперь, как только вы закончите с вашим тяжелым процессом, вызовите этот отдельно созданный метод в
onPostExecute()
.Таким образом, код psuuedo будет выглядеть следующим образом,
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. } } }
Надеюсь, это поможет,
Удачи!
Моим первым решением было использовать методы обратного вызова с реализацией интерфейса см. Пример https://stackoverflow.com/a/6396376/390177 .
Поболтав некоторое время в Android-чате, я услышал, что есть более практичное решение.
Но давайте начнем прямо сейчас.
Вы можете использовать IntentService в сочетании с PendingIntent.
Коммуникация осуществляется с намерением .
Если вы хотите использовать ProgressDialog , вам нужен собственный активность для него, которые регистрируют, например, BroadcastReciever и IntentService посылает ему фактический статус на широковещание.
Сначала мы создаем Activity , которая содержит ProgressDialog и зарегистрированный BroadcastReceiver. Устройство BroadcastReceiver прослушивает сообщения об обновлении и завершении диалога.Для деятельности нам нужен макет ...
<?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>
... и соответствующий код:
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(); } }
Теперь мы хотим использовать действие , поэтому начнем с его вызова:
Таким образом, мы имеем запущенную ProgressActivity, которая ждет различных передач. Но Сначала нам нужен IntentService , который отправляет широковещательные сообщения.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);
Итак, давайте: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); } }
Результат вычислительного прогресса должен быть доступен вродительности , поэтому мы создаемPendingIntent в том, что Activity и вызовите 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);
Для получения результатов мы должны переопределить метод
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)); } } }