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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:19:19  来源:igfitidea点击:

Android calling AsyncTask right after an another finished

androidandroid-asynctask

提问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 AsyncTaskis 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 我肯定会选择上面的选项1executeOnExecutor()是 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:

AsycnTask.execute() 文档:

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 doInBackgroundof 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 ObservableIntegeryou 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

那么,它是如何工作的

ObservableIntegerwill be looking for changes in the variable mObsInt, so lets say if mObsIntis equal to 1 it will do something, if is equal to 2 will do another thing, so, to solve this problem with 2 asynctasksis easy, when one of the asynctasksfinishes mObsIntwill be equal to 1 , if the other asyncTaskfinishes so mObsIntwill be mObsInt++, and then your mObsIntwill 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 onCreatemethod

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