Android 在另一个完成后立即调用 AsyncTask
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10048958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android calling AsyncTask right after an another finished
提问by hcpeter
I have some problem with Android AsyncTask. There is an Activity which contains some TextView a button and a picture. When an user entered this activity I start an asynctask to check whether the user can go toward from the activity (until the task not finish the button not active). Then I want to start another asyntask to get the picture. So I made an inner class:
我对 Android AsyncTask 有一些问题。有一个 Activity 包含一些 TextView 一个按钮和一张图片。当用户进入此活动时,我启动一个异步任务来检查用户是否可以从活动中前进(直到任务未完成按钮未激活)。然后我想启动另一个异步任务来获取图片。所以我做了一个内部类:
AsyncTask<String, Void, JSONObject>() authTask = new AsyncTask<String, Void, JSONObject>() {
@Override
protected JSONObject doInBackground(String... params) {
//call the rest api
}
@Override
protected void onPostExecute(JSONObject result) {
// check the result
// and make another asynctask
AsyncTask<String, Void, Bitmap> imageTask = new Async.... {
// get image
}
imageTask.execute();
}
}
and I call
authTask.execute();
from the UI thread.
我authTask.execute();
从 UI 线程调用
。
I have a bad feeling about this, especially it seems doesn't work (it's ok few times but suddenly it "freeze": no exception just hanging and the progress bar is spinning. Nothing happens and the button won't be active.) There is another way to get an information and when it's finished immediately start another task?
我对此有一种不好的感觉,尤其是它似乎不起作用(几次没问题,但突然“冻结”了:也不例外,只是挂起并且进度条在旋转。没有任何反应,按钮也不会处于活动状态。)还有另一种获取信息的方法,当它完成后立即开始另一个任务?
UDPATE: I working with api level 10. In authTask I get some information which is needed to start imageTask (some id) so I have to call these tasks in a row. In api level 10 it's is possible?
UDPATE:我使用 api 级别 10。在 authTask 中,我获得了一些启动 imageTask(某些 ID)所需的信息,因此我必须连续调用这些任务。在 api 级别 10 中可能吗?
Thanks in advance!
提前致谢!
Br, Peter
兄弟,彼得
采纳答案by ρяσ?ρ?я K
you can use getStatus()
checks whether the the AsyncTask
is pending, running, or finished.and when finsh start your new task.like:
您可以使用getStatus()
检查是否AsyncTask
正在挂起、正在运行或已完成。以及当 finsh 开始您的新任务时。例如:
if(authTask .getStatus() == AsyncTask.Status.PENDING){
// My AsyncTask has not started yet
}
if(authTask .getStatus() == AsyncTask.Status.RUNNING){
// My AsyncTask is currently doing work in doInBackground()
}
if(authTask .getStatus() == AsyncTask.Status.FINISHED){
// START NEW TASK HERE
}
example for your app:
您的应用程序示例:
btn.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
if (authTask != null && authTask.getStatus() == AsyncTask.Status.FINISHED) {
//START YOUR NEW TASK HERE
}
else
{
//IGNORE BUTTON CLICK
}
}
});
回答by Peter Ajtai
1:
1:
You could write the code for authTask and then for imageTask, one after the other, within a single doInBackground()
. This single AsyncTask instance would be fire by a single execute()
statement. This may or may not be practical depending on needed UI interactions.
您可以依次为 authTask 和 imageTask 编写代码,在一个doInBackground()
. 这个单个 AsyncTask 实例将由单个execute()
语句触发。这可能实用,也可能不实用,具体取决于所需的 UI 交互。
2:
2:
Edit: as noted by kabuku this information is mostly for HoneyComb+. Pre HoneyComb I would definitely go with option 1above. executeOnExecutor()is api level 11+
编辑:正如 kabuku 所指出的,此信息主要用于 HoneyComb+。Pre HoneyComb 我肯定会选择上面的选项1。executeOnExecutor()是 API 级别 11+
In receent versions, execute()
will send your AsyncTasks in series by default (ICS+). If you want to make sure this happens, specify the serial executor.
在最近的版本中,execute()
默认情况下将发送您的 AsyncTasks (ICS+)。如果要确保发生这种情况,请指定串行执行程序。
In your case this would be:
在您的情况下,这将是:
authTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
// Image task will only be done AFTER textViewTask is done
imageTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
And for newer versions a simple
对于较新的版本,一个简单的
...
// ICS+ and pre honeycomb (I think)
authTask.execute();
// Image task will only be done AFTER textViewTask is done
imageTask.execute();
...
From the AsycnTask.execute() documentation:
Note: this function schedules the task on a queue for a single background thread or pool of threads depending on the platform version. When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. After HONEYCOMB, it is planned to change this back to a single thread to avoid common application errors caused by parallel execution.
注意:此函数根据平台版本为单个后台线程或线程池安排队列中的任务。首次引入时,AsyncTasks 在单个后台线程上串行执行。从 DONUT 开始,这已更改为允许多个任务并行操作的线程池。HONEYCOMB 之后,计划将其改回单线程,以避免并行执行导致的常见应用程序错误。
PS:
To run tasks independent of each other you must use the AsyncTask.THREAD_POOL_EXECUTOR
. That requires a different executor:
PS:要运行彼此独立的任务,您必须使用AsyncTask.THREAD_POOL_EXECUTOR
. 这需要一个不同的执行者:
// Go parallel! (NOT what you want)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
回答by waqaslam
Its not a good design to nest AsyncTask. Do all the heavy lifting in doInBackgroundand simply post/update the results. In other words, combine the processing of second AsyncTask in your first one.
嵌套 AsyncTask 并不是一个好的设计。在doInBackground 中完成所有繁重的工作,然后简单地发布/更新结果。换句话说,在你的第一个 AsyncTask 中结合第二个 AsyncTask 的处理。
回答by Alex Gitelman
From the code that you showed it does not seem to make sense to spawn second task. Just get you image inside doInBackground
of the first task right after authorization.
If you need to update UI in between, you can do it in progress update.
从您展示的代码来看,生成第二个任务似乎没有意义。只需doInBackground
在授权后立即在第一个任务中获取图像。如果您需要在两者之间更新 UI,您可以在进行中更新。
回答by CooL AndroDev
int count;
private void attemptConnect()
{
count = 0;
str_lang = "English";
str_wait = "Plaese Wait";
new AllQuestion().execute();
}
private class AllQuestion extends AsyncTask<String, String, String> {
ProgressDialog pg;
@Override
protected void onPreExecute() {
super.onPreExecute();
pg = new ProgressDialog(LanguageActivity.this);
pg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pg.setMessage(str_wait);
pg.setCancelable(false);
pg.show();
}
@Override
protected String doInBackground(String... strings) {
try {
SoapObject soapObject = new SoapObject(AppConstant.NAMESPACE, AppConstant.QUESTION_SOAP_METHOD);
soapObject.addProperty("language", str_lang);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(soapObject);
HttpTransportSE se = new HttpTransportSE(AppConstant.webUrl);
se.call(AppConstant.QUESTION_SOAP_ACTION, envelope);
Object responce = envelope.getResponse();
Log.d("Question List:=>>", "" + responce);
return responce.toString();
} catch (Exception e) {
e.printStackTrace();
pg.dismiss();
return null;
}
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (pg.isShowing()) {
pg.dismiss();
Log.i(TAG, s);
if (s != null || !s.equalsIgnoreCase("")) {
try {
JSONArray array = new JSONArray(s);
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
String queId = obj.getString(TAG_QID);
String que = obj.getString(TAG_QUE);
String str_Opt = obj.getString(TAG_OPT);
question = new Question(queId, que, str_lang, str_catId, str_Opt, manager.getDateTime());
helper.insertQuestion(question);
}
count++;
if (count < 5) {
if (count == 1) {
str_lang = "German";
str_wait = "bitte warte einen Moment";
new AllQuestion().execute();
}
if (count == 2) {
str_lang = "Italian";
str_wait = "per favore aspetta un momento";
new AllQuestion().execute();
}
if (count == 3) {
str_lang = "Chinese";
str_wait = "请稍候";
new AllQuestion().execute();
}
if (count == 4) {
str_lang = "French";
str_wait = "patientez s'il-vous-plait";
new AllQuestion().execute();
}
Log.d("All Question:-", question.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
}
回答by Gastón Saillén
I have solved this kind of problem when i had to download something from a database before login in the user into the app, with this i fixed this problem.
当我必须在用户登录应用程序之前从数据库下载某些内容时,我已经解决了这种问题,我解决了这个问题。
To use ObservableInteger
you can do this
要使用ObservableInteger
你可以这样做
first declare it
先声明一下
private ObservableInteger mObsInt;
then in your onCreate you will have a listener waiting for the values of the mObsInt to change, after those values change you can do anything you want
然后在你的 onCreate 你将有一个监听器等待 mObsInt 的值改变,在这些值改变后你可以做任何你想做的事情
//Listener
mObsInt = new ObservableInteger();
mObsInt.set(0);
mObsInt.setOnIntegerChangeListener(new OnIntegerChangeListener()
{
@Override
public void onIntegerChanged(int newValue)
{
if (mObsInt.get()==1)
//Do something if the first asyncTask finishes
if (mObsInt.get()==2){
//Do something if the second asyncTask finishes, in this case i just go to another activity when both asyncTasks finish
Intent mainIntent = new Intent().setClass(LoginActivity.this, Principal.class);
startActivity(mainIntent);
finish();
}
}
});
So, how it works
那么,它是如何工作的
ObservableInteger
will be looking for changes in the variable mObsInt
, so lets say if mObsInt
is equal to 1 it will do something, if is equal to 2 will do another thing, so, to solve this problem with 2 asynctasks
is easy, when one of the asynctasks
finishes mObsInt
will be equal to 1 , if the other asyncTask
finishes so mObsInt
will be mObsInt++
, and then your mObsInt
will be equal to 2, the listener will be waiting for the values, and then do what you want to do when the values match your if statment at the onCreate
method
ObservableInteger
将寻找变量的变化mObsInt
,所以假设如果mObsInt
等于 1 它会做一些事情,如果等于 2 会做另一件事,所以,用 2 解决这个问题asynctasks
很容易,当其中一个asynctasks
完成mObsInt
时等于 1 ,如果另一个asyncTask
完成,那么mObsInt
将是mObsInt++
,然后你mObsInt
将等于 2,侦听器将等待值,然后在值与onCreate
方法中的 if 语句匹配时执行您想做的事情
now, just in your asynctasks just put in your onPostExecute() method this line
现在,只需在您的异步任务中放入您的 onPostExecute() 方法这一行
mObsInt.set(mObsInt.get()+1);
so if the first async finish, mObsint == 1 , if the second finish mObsInt == 2, and then you handle what you want to do in your onCreate method
所以如果第一个异步完成, mObsint == 1 ,如果第二个完成 mObsInt == 2,然后你在你的 onCreate 方法中处理你想做的事情
hope this helps for you, it helped me
希望这对你有帮助,它帮助了我
You can get more info at this doc : https://developer.android.com/reference/android/databinding/ObservableInt.html
您可以在此文档中获得更多信息:https: //developer.android.com/reference/android/databinding/ObservableInt.html
happy coding !
快乐编码!
回答by AmirHossein Manian
I have an idea to make async series in just one async task:
我有一个想法在一个异步任务中制作异步系列:
protected Boolean doInBackground(String... params) {
if(params[0] == "taskA") {
//do somthing
params[0] = "taskB";
}
if(params[0] == "taskB") {
//do somthing
params[0] = "taskC";
}
if(params[0] == "taskC") {
//do somthing
params[0] = "taskD";
}
if(params[0] == "taskD") {
//do somthing
return true;
}
And in your main thread just call async task like this:
在您的主线程中,只需像这样调用异步任务:
ShowMyProgress(); //if you like
new MyAsyncTask().execute("taskA");
And finally you can hide your progress on onPostExecute like:
最后,您可以在 onPostExecute 上隐藏您的进度,例如:
protected void onPostExecute(final Boolean success) {
if (success) {
....
HideMyProgress();
}
}