如何在Android中从异步任务返回值

7

我创建了一个异步任务来调用我的服务器从数据库获取数据。
我需要处理从http服务器调用返回的结果。
从我的活动中,在许多地方调用异步任务。所以我不能使用成员变量来访问结果。有没有什么办法可以做到这一点?

public Result CallServer(String params)
{

    try
    {
    new MainAynscTask().execute(params);
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
    return aResultM;//Need to get back the result

}  

    private class MainAynscTask extends AsyncTask<String, Void, Result> {


    @Override
    protected Result doInBackground(String... ParamsP) {    
        //calling server codes
        return aResultL;
    }       
    @Override
       protected void onPostExecute(Result result) {
          super.onPostExecute(result);
          //how i will pass this result where i called this task?
       }

1
为什么不按照https://dev59.com/pWox5IYBdhLWcg3wDgTR#9458274中所示调用处理该值的方法? - rarp
可能是异步的重复和异步与 - Usman Kurd
正确的方法是使用协议 - IgniteCoders
4个回答

15
尝试在调用execute()方法后调用AsyncTask的get()方法,这对我有效。 http://developer.android.com/reference/android/os/AsyncTask.html#get()
public Result CallServer(String params)
{
   try
   {
       MainAynscTask task = new MainAynscTask();
       task.execute(params);
       Result aResultM = task.get();  //Add this
   }
   catch(Exception ex)
   {
       ex.printStackTrace();
   }
   return aResultM;//Need to get back the result

} 
...
...

2
AsyncTask在其他线程中执行,如果您尝试这样做,当任务未结束从服务器获取数据时,您的主线程将被冻结,活动无法处理用户触摸屏幕的事件。 - IgniteCoders
1
我不建议像上面那样使用get,因为赋值是同步的。 - JackAW
这样做可以实现功能,但肯定不是一个可采用的方式。这对于教育项目来说很好,但不适用于实时应用程序。 原因:它使应用程序在保持主线程的同时变得缓慢,这违背了使用异步任务的整个目的。 - Antroid

3
我可以提供两种方法:
  1. 使用AsyncTask中的onPostExecute(Result)方法。请参见http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)

  2. 发送一个带有结果作为额外信息的广播。

AsyncTask是异步任务,所以将结果返回给调用者是没有意义的。相反,在onPostExecute()中处理结果,例如将值设置到TextView中,或者发送一个广播,让其他监听器来处理结果。

一个小提示:如果你正在从onPostExecute()访问View(例如从另一个线程),请在Activity.runOnUiThread(...)内部执行。别忘了,onPostExecute()在UI线程上调用。 - naXa stands with Ukraine

1
这是我解决问题的方法:
1)创建一个接口类,定义一个在完成时执行的方法签名:
public interface AsyncIfc {
    public void onComplete();
}

2) 在您的AsyncTask类中设置一个属性来保存委托方法:

    public AsyncIfc completionCode;

3) 在AsyncTask的onPostExecute()中触发委托:

completionCode.onComplete();

4) 从您的调用逻辑中,将委托属性设置为匿名方法:

task.completionCode = new AsyncIfc() {

    @Override
    public void onComplete() {
    // Any logic you want to happen after execution
    }
};

0
当执行异步任务时,任务经历了4个步骤:
  1. onPreExecute(),在任务执行之前在UI线程上调用。通常用于设置任务,例如在用户界面中显示进度条。

  2. doInBackground(Params...),在onPreExecute()完成后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数传递到此步骤。计算的结果必须由此步骤返回,并将传递回最后一步。此步骤还可以使用publishProgress(Progress...)发布一个或多个进度单元。这些值在UI线程上发布,在onProgressUpdate(Progress...)步骤中。

  3. onProgressUpdate(Progress...),在调用publishProgress(Progress...)后在UI线程上调用。执行的时间未定义。此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。例如,它可以用于动画化进度条或在文本字段中显示日志。

  4. onPostExecute(Result),在后台计算完成后在UI线程上调用。将后台计算的结果作为参数传递给此步骤。

使用Handler

在你的活动中

    Handler mHandler = new Handler() { 
    @Override public void handleMessage(Message msg) { 
        String s=(String)msg.obj;
        tv.setText(s);
    }
};

//result is soap object in this case.
protected void onPostExecute(SoapObject result) {
    pd.dismiss();
    if(result != null) {
        Message msg=new Message();
        msg.obj=result.getProperty(0).toString();
        mHandler.sendMessage(msg);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接