【问题标题】:Return value from AsyncTask without get() method没有 get() 方法的 AsyncTask 的返回值
【发布时间】:2013-10-31 11:02:47
【问题描述】:

我正在尝试从 DoInBackground 中的异步任务返回值,但调用 get() 方法会冻结我的 UI。如何将我的代码重写为回调方法? :

public class GetUrlDataTask extends AsyncTask<String, Integer, String> {
String response;
HttpUtils util;
@Override
protected String doInBackground(String... params) {
    try {
        util = new HttpUtils(params[0]);
        response = util.getContent();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return response;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
}

在我的活动中,我得到response = new GetUrlDataTask().execute("site").get;的结果

【问题讨论】:

  • 这与异步完全相反。您需要使用回调。
  • 您可以将意图与广播接收器或事件总线一起使用,回调也是一个好主意
  • 您可以将其设为内部类并直接从onPostExecute()see this answer 调用Activity 方法,了解如何使用interfaceAsyncTask

标签: android http android-asynctask


【解决方案1】:

[更新] 现在我建议使用注释。使用注释,您可以注入视图,只需几个字母即可在编译步骤中作为异步进程运行。查看 github 上的黄油刀库。

ButterKnife

您可以创建接口,将其传递给AsyncTask(在构造函数中),然后在onPostExecute中调用方法

例如:

你的界面:

public interface OnTaskCompleted{
    void onTaskCompleted();
}

您的活动:

public YourActivity implements OnTaskCompleted{
    //your Activity
}

还有你的 AsyncTask:

public YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type
    private OnTaskCompleted listener;

    public YourTask(OnTaskCompleted listener){
        this.listener=listener;
    }

    //required methods

    protected void onPostExecute(Object o){
        //your stuff
        listener.onTaskCompleted();
    }
}

【讨论】:

  • 在回调中有空经验。 YourTask 如何知道我的活动包含的变量?
  • @Flextra Iam get Object in onPostExecute 如何将该对象设置为 autoText 并执行另一个 AsynchronusTask 请帮助我
【解决方案2】:

如果 Async 任务需要花费相当长的时间(通常是这样),则不应使用 .get()。

相反,您可以使用消息/处理程序/服务/等,也可以简单地使用 onPostExecute(Result) 方法。

编辑:新代码。根据您的描述,您似乎需要使用接口。

如果您需要在另一个类中拥有 Asynctask,那么接口可能是您的最佳选择。

TestTask.java(您单独的 Asynctask):

import android.os.AsyncTask;

// Remember to change object type <> to what you need
public class TestTask extends AsyncTask<Object,Object,Object> {

    public interface OnTaskCompleted{
        void onTaskCompleted();
    }

    private OnTaskCompleted listener;

    public TestTask(OnTaskCompleted listener){
        this.listener = listener;
    }

    protected void onPostExecute(Object o){
        // Call the interface method
        if (listener != null)
            listener.onTaskCompleted();
    }

    @Override
    protected Object doInBackground(Object... params) {
        // The sleep() is just to simulate activity and delay
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

MainActivity.java(或任何其他活动):

public class MainActivity extends Activity {

private boolean status = false;

private OnTaskCompleted listener = new OnTaskCompleted() {
    public void onTaskCompleted() {
        status = true;
        Toast.makeText(MainActivity.this, "Status: " + status, Toast.LENGTH_SHORT).show();
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toast.makeText(MainActivity.this, "Status: " + status, Toast.LENGTH_SHORT).show();
    new TestTask(listener).execute("Testing");
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}

【讨论】:

  • 我有另一个带有 asynctask 的类也有同样的问题,但它非常大,我可以将它包含在我的活动类中。
  • 更新了原始版本以反映您的需求。上面的代码已经过测试并且可以工作。您可以更改界面以执行您需要的操作。接口的思想或多或少是让Asynctask调用的方法在Activity内部执行,由此产生了回调的概念。
  • 但是我仍然不明白如何返回值。我需要在 onTaskCompleted(); 中写一些作为“返回字符串”的东西?
  • 等待返回值会冻结你的 UI。相反,显示一个对话框或状态指示器,并在 Asynctask 完成时更新 UI。如果您有另一个需要返回值的方法,那么您应该重构您的代码,并在使用回调后继续。这样你的用户界面就不会等待
【解决方案3】:

我不喜欢将 AsycTask 任务放在单独的类中,尤其是当您需要使用响应时。考虑到作为内部类实现时的容易程度,它使得与响应和局部变量的交互变得过于困难。

我猜你把它放在自己的类中,这样你就可以重用它。我会考虑将 AsycTask 保留为内部类,并在 doInBackground() 中调用外部可重用对象/方法。这将保持代码 DRY 并允许您的 Activity 对响应执行所需的操作。

public class MyActivity extends Activity {
    TextView textview;

    //...

    private class GetUrlTask extends AsyncTask<String, Integer, String> {

        protected String doInBackground(String... params) {
            return new GetHttpResponse().get(params[0]);
        }

        protected void onPostExecute(String response) {
            //Do UI updates...
            textview.setText(response);
        }
    }
}


public class GetHttpResponse {

    public String get(String url) {
        try {
            util = new HttpUtils(url);
            response = util.getContent();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    return response;
    }
}

【讨论】:

  • 如果我有另外三个使用此任务的活动怎么办?
【解决方案4】:

你可以这样做:

public class MyActivity extends Activity
{
  public void someMethod()
  {
    // Here you could put up a ProgressDialog

    GetUrlDataTask myTask = new GetUrlDataTask();
    myTask.execute();
  }

  public class GetUrlDataTask extends AsyncTask<String, Integer, String>
  {
    @Override
    protected String doInBackground(String... params)
    {
      String response = null;
      HttpUtils util;

      try
      {
        util = new HttpUtils(params[0]);
        response = util.getContent();
      }
      catch (Exception e)
      {
        e.printStackTrace();
        response = e.getMessage();
      }
      return response;
    }

    @Override
    protected void onPostExecute(String result)
    {
      // Here you can dismiss the ProgressDialog and display the result
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-25
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 2015-08-19
    相关资源
    最近更新 更多