我有一个方法public void writeEntry(Activity ctx, Entry entry)
,它可以获取一些数据并且必须调用本机方法,这需要更长时间才能完成。
所以我创建了一个 AsyncTask 来处理 ProgressDialog 和本机方法。它在自己的 Activity 中运行良好来测试它,在 Activity 中我使用了一个回调接口等等。
在我的情况下,我有上述方法,必须执行 AsyncTask 。执行不能在该方法中,因为它不会停止进一步的执行
在继续执行之前,我需要本机方法的结果
有没有可能等待 AsyncTask 直到它完成?方法wait()
不是一个选项,因为UI线程也会等待,因此 ProgressDialog 的意义将会丢失。
我可以使用给定参数中的方法runOnUiThread()
,还是启动自己的活动的唯一解决方案?
答案 0 :(得分: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.
}
}
}
希望这会有所帮助,
祝你好运!
答案 1 :(得分:3)
我的第一个解决方案是使用带有接口实现的回调方法,请参阅示例https://stackoverflow.com/a/6396376/390177。
在Android聊天中聊了一会儿之后,我听说有一个更加普遍的解决方案
您可以将 IntentService 与 PendingIntent 结合使用。
通过 Intent 实现通信
如果要使用 ProgressDialog ,则需要一个自己的 Activity ,例如注册 BroadcastReciever 和 IntentService < / em>每个广播发送实际状态。
但是现在就开始吧 首先,我们创建 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();
}
}
现在我们要使用 Activity ,所以我们先来调用它:
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 中提供,因此我们在 Activity 中创建 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));
}
}
}
这就是魔术,我希望它能帮到你。