[英]Get AsyncTask's result without blocking the thread
I have the code that sends requests to REST API in AsyncTask. 我有将请求发送到AsyncTask中的REST API的代码。 Also, I have a ProgressDialog initialization in preExecute()
and its dismission in postExecute()
. 另外,我有一个ProgressDialog初始化preExecute()
及其在解聘postExecute()
I want ProgressDialog to show an indeterminate spinner (you know, that loading animation), but I need to get a result too. 我希望ProgressDialog显示一个不确定的微调器(您知道正在加载动画),但是我也需要获得结果。 get()
blocks the main thread where I'm invoking it in - what's the workaround for that case? get()
在我调用它的地方阻塞了主线程-这种情况的解决方法是什么?
Main thread (main activity) 主线程(主要活动)
LoginTask task_login = new LoginTask();
AsyncTask<String, Void, JSONObject> response = task_login.execute(et_username.getText().toString(), et_password.getText().toString());
try {
JSONObject json = response.get();
Toast.makeText(MainActivity.this, json.toString(), Toast.LENGTH_SHORT).show();
} catch (InterruptedException e) {
Toast.makeText(MainActivity.this, "Interrupted.", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
AsyncTask (dummy doInBackground): AsyncTask(虚拟doInBackground):
public class LoginTask extends AsyncTask<String, Void, JSONObject> {
private LoginTask self = this;
private ProgressDialog progressDialog;
@Override
protected JSONObject doInBackground(String... params) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(MainActivity.context,
"Logging in...", "");
progressDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
MainActivity.context.getResources().getResourceEntryName(R.string.dialog_button_cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
self.cancel(true);
}
});
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
progressDialog.dismiss();
}
}
You can use AsyncTask's onProgressUpdate() method to perform the actions on the UI thread (such as showing or updating a loading animation) while doInBackGround() does the background work on another thread. 您可以使用AsyncTask的onProgressUpdate()方法在UI线程上执行操作(例如显示或更新加载动画),而doInBackGround()在另一线程上执行后台工作。
Basically you invoke the publishProgress() method from within doInBackGround(), which in turn calls onProgressUpdate(). 基本上,您从doInBackGround()中调用publishProgress()方法,该方法又调用onProgressUpdate()。
Check out the Android reference page on AsyncTask for an example. 请查看AsyncTask上的Android参考页面以获取示例。
1 - You can use a callback method. 1-您可以使用回调方法。 but keep in mind you should call it in your main thread. 但请记住,您应该在主线程中调用它。
2 - you can use LocalBroadcastManager
in order to send your result through Intent
. 2-您可以使用LocalBroadcastManager
来通过Intent
发送结果。
3 - you might want to use in application messaging libraries which are more reliable in my opinion. 3-在我看来,您可能想在应用程序消息传递库中使用更可靠的消息。 one example which I use very often is EventBus
. 我经常使用的一个示例是EventBus
。
Please look at the usage of AsyncTask https://developer.android.com/reference/android/os/AsyncTask#usage 请查看AsyncTask的用法https://developer.android.com/reference/android/os/AsyncTask#usage
There is a callback function onPostExecute
which returns (as parameter) the value you requested: 有一个回调函数onPostExecute
,它返回(作为参数)您请求的值:
private class RestTask extends AsyncTask<Object, Object, String> {
protected String doInBackground(Object... args) {
// this happend on background thread
return downloadData();
}
protected void onPreExecute() {
// this happend on UI thread
showSpinner();
}
protected void onPostExecute(String result) {
// this happend on UI thread
hideSpinner();
doSomethingWithDownloadResult(result);
}
}
Usage: 用法:
new RestTask().execute()
As you edited the question, this: 当您编辑问题时,这是:
try {
JSONObject json = response.get();
Toast.makeText(MainActivity.this, json.toString(), Toast.LENGTH_SHORT).show();
} catch (InterruptedException e) {
Toast.makeText(MainActivity.this, "Interrupted.", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
should be called in previous Tasks onPostExecute
method, this way you will not block you UI with get
method waiting on login result. 应该在先前的Tasks onPostExecute
方法中调用,这样您就不会使用get
方法等待登录结果来阻止UI。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.