2011-06-17 64 views
4

我有一个方法public void writeEntry(Activity ctx, Entry entry)它获得一些数据,必须调用本地方法,这需要更长的时间才能完成。
所以我创建了一个AsyncTask它处理ProgressDialog和本地方法。它在自己的活动很好测试它,在那活动我使用了一个回调接口等。等待与ProgressDialog执行AsyncTask

在我的情况下,我有上述方法,必须执行AsyncTask。执行不能在该方法,因为它不停止进一步执行。
我需要从本地方法的结果之前,我可以与执行下去。
是否有任何可能性等待AsyncTask直到它完成?该方法wait()是不是一种选择,因为UI线程等待,太等的ProgressDialog感将会丢失。

我可以使用给定参数中的方法runOnUiThread()还是唯一可以启动自己的解决方案活动

+0

那里,在哪里?我对活动描述感到困惑。你能写一些名字,而不是使用“there”,所以我们知道我们正在查看多少不同的活动,谢谢其他人,只是在你的问题中转储相关的代码:) – doNotCheckMyBlog

+0

我已经编辑过问。我希望现在清楚。通常只有主* Activity *,它调用writeEntry()方法。 – CSchulz

+0

我试图理解它,所以基本上你有wrtieEntry方法执行AsyncTask但(writeEntry)代码执行不断。但是你希望代码等到asynctask完成它的工作。我对吗? – doNotCheckMyBlog

回答

3

我的第一个解决方案是使用具有接口实现的回调方法,请参阅示例https://stackoverflow.com/a/6396376/390177

在Android聊天中聊了一会之后,我听说有一种更可行的解决方案。
您可以使用IntentService结合PendingIntent
通讯实现意图's。
如果你想使用ProgressDialog,你需要为它的自己的活动,其注册例如BroadcastRecieverIntentService将它基于广播的实际状态。

但是让我们现在就开始。
首先,我们创建了活动,其中包含ProgressDialog和注册广播接收器。该广播接收器听取有关更新和整理对话框消息。

对于活动我们需要布局...

<?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(); 
    } 
} 

现在,我们要使用的活动,所以让从调用它开始:

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); 

所以我们需要一个正在运行的ProgressActivity,它等待不同的广播。但首先我们需要发送广播的IntentService
所以让我们去:

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); 
    } 
} 

的计算进步的结果应是在parentActivity可用的,所以我们在活动创建的PendingIntent并调用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)); 
     } 
    } 
} 

这是神奇的,我希望它会帮助你。

4

,所以我会尽量解释,就像我可以

启动一个的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. 
     } 
    } 

} 

希望这将帮助,

祝您好运!

+0

如何等待该代码片段的* AsyncTask *的结果,而不冻结UI线程? – CSchulz