30

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

authTask.execute(); 从 UI 线程调用。

我对此有一种不好的感觉,尤其是它似乎不起作用(几次都没问题,但突然它“冻结”:没有例外,只是挂起并且进度条在旋转。没有任何反应,按钮也不会激活。)还有另一种获取信息的方法,当它完成后立即开始另一个任务?

UDPATE:我使用 api 级别 10。在 authTask 中,我得到了一些启动 imageTask 所需的信息(一些 id),所以我必须连续调用这些任务。在 api 级别 10 有可能吗?

提前致谢!

兄弟,彼得

4

7 回答 7

27

您可以使用getStatus()检查是否处于AsyncTask挂起、正在运行或已完成。以及何时开始您的新任务。如:

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
}

您的应用的示例:

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
        }
      }
   }); 
于 2012-04-06T20:48:57.243 回答
22

1:

您可以在一个doInBackground(). 此单个 AsyncTask 实例将由单个execute()语句触发。根据所需的 UI 交互,这可能实用也可能不实用。


2:

编辑:正如 kabuku 所指出的,此信息主要用于 HoneyComb+。Pre HoneyComb 我肯定会选择上面的选项1executeOnExecutor()是 api 级别 11+

在最近的版本execute()中,默认情况下将发送您的 AsyncTasks (ICS+)。如果要确保发生这种情况,请指定串行执行程序。

在您的情况下,这将是:

authTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
// Image task will only be done AFTER textViewTask is done
imageTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);

对于较新的版本,一个简单的

...
// ICS+ and pre honeycomb (I think)
authTask.execute();
// Image task will only be done AFTER textViewTask is done
imageTask.execute();
...

AsycnTask.execute() 文档中:

注意:此函数根据平台版本将任务安排在单个后台线程或线程池的队列中。首次引入时,AsyncTask 在单个后台线程上串行执行。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。在 HONEYCOMB 之后,计划将其改回单线程,以避免并行执行导致的常见应用程序错误。


PS:要运行彼此独立的任务,您必须使用AsyncTask.THREAD_POOL_EXECUTOR. 这需要一个不同的执行者:

// Go parallel! (NOT what you want)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
于 2012-04-06T21:05:32.480 回答
5

嵌套 AsyncTask 并不是一个好的设计。在doInBackground中完成所有繁重的工作并简单地发布/更新结果。换句话说,将第二个 AsyncTask 的处理合并到你的第一个中。

于 2012-04-06T20:41:42.873 回答
1

从您展示的代码来看,生成第二个任务似乎没有意义。只需doInBackground在授权后立即让您在第一个任务中获得图像。如果您需要在两者之间更新 UI,您可以在进行中更新。

于 2012-04-06T20:42:56.580 回答
1
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();
                }
            }
        }
    }

}
于 2016-10-06T12:55:45.213 回答
0

我有一个想法在一个异步任务中制作异步系列:

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

在你的主线程中,只需像这样调用异步任务:

ShowMyProgress(); //if you like
new MyAsyncTask().execute("taskA");

最后,您可以在 onPostExecute 上隐藏您的进度,例如:

protected void onPostExecute(final Boolean success) {
        if (success) {
            ....

            HideMyProgress();
        }
}
于 2016-08-27T04:59:49.927 回答
0

当我必须在用户登录到应用程序之前从数据库下载某些东西时,我已经解决了这种问题,我解决了这个问题。

要使用ObservableInteger你可以这样做

首先声明它

private ObservableInteger mObsInt;

然后在你的 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();
                }
            }
        });

那么,它是如何工作的

ObservableInteger将寻找变量的变化mObsInt,所以让我们说如果mObsInt等于 1 它会做某事,如果等于 2 会做另一件事,所以,用 2 解决这个问题asynctasks很容易,当其中一个asynctasks完成mObsInt时等于 1 ,如果其他asyncTask完成,那么mObsInt将是mObsInt++,然后您将等于 2,侦听器将等待值,然后当值与方法mObsInt中的 if 语句匹配时执行您想要执行的操作onCreate

现在,只需在您的 asynctasks 中放入您的 onPostExecute() 方法这一行

mObsInt.set(mObsInt.get()+1);

所以如果第一个异步完成,mObsint == 1,如果第二个完成 mObsInt == 2,然后你在 onCreate 方法中处理你想要做的事情

希望这对你有帮助,它帮助了我

您可以在此文档中获得更多信息:https ://developer.android.com/reference/android/databinding/ObservableInt.html

快乐编码!

于 2018-05-08T13:12:30.193 回答