在Android中从AsyncTask返回值

一个简单的问题:是否有可能在AsyncTask返回一个值?

 //AsyncTask is a member class private class MyTask extends AsyncTask<Void, Void, Void>{ protected Void doInBackground(Void... params) { //do stuff return null; } @Override protected void onPostExecute(Void result) { //do stuff //how to return a value to the calling method? } } 

然后在我的Activity / Fragment

 // The task is started from activity myTask.execute() // something like this? myvalue = myTask.getvalue() 

编辑:这是很久以前问我在哪里我不熟悉Java,现在我更好,我会做一个快速总结:

asynchronous任务的要点是任务是asynchronous ,这意味着在任务上调用execute()之后,任务将开始在其自己的线程上运行。 从asynctask返回一个值将是毫无意义的,因为原来的调用线程已经继续做其他的东西(因此任务是asynchronous的)。

想想时间:在某个时间点,你开始了一个与主线程并行运行的任务。 当并行运行任务完成时,主线程上的时间也已经过去了。 并行任务不能及时返回值给主线程。

我是从C来的,所以对这个我不太了解。 但似乎很多人都有同样的问题,所以我想我会澄清一点。

为什么不调用处理值的方法?

 public class MyClass extends Activity { private class myTask extends AsyncTask<Void, Void, Void> { //initiate vars public myTask() { super(); //my params here } protected Void doInBackground(Void... params) { //do stuff return null; } @Override protected void onPostExecute(Void result) { //do stuff myMethod(myValue); } } private myHandledValueType myMethod(Value myValue) { //handle value return myHandledValueType; } } 

这就是onPostExecute()的用途。 它在UI线程上运行,并且可以将结果从那里传递到屏幕(或其他您需要的任何地方)。 直到最终结果可用,它才会被调用。 如果你想提供中间结果,请看onProgressUpdate()

最简单的方法是将调用对象传递给asynchronous任务(如果你喜欢,可以在构造它时使用):

 public class AsyncGetUserImagesTask extends AsyncTask<Void, Void, Void> { private MyImagesPagerFragment mimagesPagerFragment; private ArrayList<ImageData> mImages = new ArrayList<ImageData>(); public AsyncGetUserImagesTask(MyImagesPagerFragment imagesPagerFragment) { this.mimagesPagerFragment = imagesPagerFragment; } @Override public Void doInBackground(Void... records) { // do work here return null; } @Override protected void onPostExecute(Void result) { mimagesPagerFragment.updateAdapter(mImages); } } 

并且在调用类(您的活动或片段)中执行任务:

 public class MyImagesPagerFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { AsyncGetUserImagesTask mGetImagesTask = new AsyncGetUserImagesTask(this); mGetImagesTask.execute(); } 

然后onPostExecuteMethod将调用你喜欢的原始类的任何方法,例如:

  public void updateAdapter(List<ImageData> images) { mImageAdapter.setImages(images); mImageAdapter.notifyDataSetChanged(); } } 

你可以试试这个: myvalue = new myTask().execute().get(); 减去它会冻结进程,直到asyncron不会完成;

您需要使用“协议”委托或提供数据到AsynTask

代表和数据源

委托是一个对象,当该对象在程序中遇到事件时,代表另一个对象或与之协调。 ( 苹果定义 )

协议是定义一些方法来委托一些行为的接口。


DELEGATE 从后台线程中的对象中获取事件


AsynkTask:

 public final class TaskWithDelegate extends AsyncTask<..., ..., ...> { //declare a delegate with type of protocol declared in this task private TaskDelegate delegate; //here is the task protocol to can delegate on other object public interface TaskDelegate { //define you method headers to override void onTaskEndWithResult(int success); void onTaskFinishGettingData(Data result); } @Override protected Integer doInBackground(Object... params) { //do something in background and get result if (delegate != null) { //return result to activity delegate.onTaskFinishGettingData(result); } } @Override protected void onPostExecute(Integer result) { if (delegate != null) { //return success or fail to activity delegate.onTaskEndWithResult(result); } } } 

活动:

 public class DelegateActivity extends Activity implements TaskDelegate { void callTask () { TaskWithDelegate task = new TaskWithDelegate; //set the delegate of the task as this activity task.setDelegate(this); } //handle success or fail to show an alert... void onTaskEndWithResult(int success) { } //handle data to show them in activity... void onTaskFinishGettingData(Data result) { } } 

编辑:如果您在doInBackground中调用委托,并且委托尝试编辑某个视图,则会崩溃,因为视图只能由主线程操纵。


额外

DATASOURCE:将数据提供给后台线程中的对象


的AsyncTask:

 public final class TaskWithDataSource extends AsyncTask<..., ..., ...> { //declare a datasource with type of protocol declared in this task private TaskDataSource dataSource; private Object data; //here is the task protocol to can provide data from other object public interface TaskDataSource { //define you method headers to override int indexOfObject(Object object); Object objectAtIndex(int index); } @Override protected void onPreExecute(Integer result) { if (dataSource != null) { //ask for some data this.data = dataSource.objectAtIndex(0); } } @Override protected Integer doInBackground(Object... params) { //do something in background and get result int index; if (dataSource != null) { //ask for something more index = dataSource.indexOfObject(this.data); } } } 

活动:

 public class DataSourceActivity extends Activity implements TaskDataSource { void callTask () { TaskWithDataSource task = new TaskWithDataSource; //set the datasource of the task as this activity task.setDataSource(this); } //send some data to the async task when it is needed... Object objectAtIndex(int index) { return new Data(index); } //send more information... int indexOfObject(Object object) { return new object.getIndex(); } } 

代码示例活动使用AsyncTask在后台线程中获取值,然后AsyncTask通过调用processValue将结果返回给Activity:

 public class MyClass extends Activity { private void getValue() { new MyTask().execute(); } void processValue(Value myValue) { //handle value //Update GUI, show toast, etc.. } private class MyTask extends AsyncTask<Void, Void, Value> { @Override protected Value doInBackground(Void... params) { //do stuff and return the value you want return Value; } @Override protected void onPostExecute(Value result) { // Call activity method with results processValue(result); } } } 

为了得到一个AsyncTask的结果,需要在super.onPostExcecute(result)之后执行。 因为这意味着背景和AsyncTask也完成了。 例如:

  ... into your async task @Override protected void onPostExecute(MyBeanResult result) { if (dialog.isShowing()) { dialog.dismiss(); } if (mWakeLock.isHeld()) { mWakeLock.release(); } super.onPostExecute(result); MyClassName.this.checkResponseForIntent(result); } 

和方法checkResponseForIntent可能是这样的:

 private void checkResponseForIntent(MyBeanResult response) { if (response == null || response.fault != null) { noServiceAvailable(); return; } ... or do what ever you want, even call an other async task... 

我使用AsyncTask中的.get()方法解决了这个问题,并且ProgressBar根本无法使用get(),实际上只有在doInBackground完成后才能使用。 我希望这对你有所帮助。

使用通用参数

 AsyncTask<Params, Progress, Result> 
  • Params – 任务的input数据types
  • Progress – 如何向全世界通报进展情况
  • Result – 任务的输出数据types

想想

 Result = task(Params) 

通过stringURL加载YourObject

  new AsyncTask<String, Void, YourObject>() { @Override protected void onPreExecute() { /* Called before task execution; from UI thread, so you can access your widgets */ // Optionally do some stuff like showing progress bar }; @Override protected YourObject doInBackground(String... url) { /* Called from background thread, so you're NOT allowed to interact with UI */ // Perform heavy task to get YourObject by string // Stay clear & functional, just convert input to output and return it YourObject result = callTheServer(url); return result; } @Override protected void onPostExecute(YourObject result) { /* Called once task is done; from UI thread, so you can access your widgets */ // Process result as you like } }.execute("http://www.example.com/"); 

将MainActivity传递给Async类,所以你将访问内部类的MainActivity函数,这对我来说很好:

 public class MainActivity extends ActionBarActivity { void callAsync() { Async as = new Async(this,12,"Test"); as.execute(); } public void ReturnThreadResult(YourObject result) { // TO DO: // print(result.toString()); } } public class Async extends AsyncTask<String, String, Boolean> { MainActivity parent; int param1; String param2; public Async(MainActivity parent,int param1,String param2){ this.parent = parent; this.param1 = param1; this.param2 = param2; } @Override protected void onPreExecute(){}; @Override protected YourObject doInBackground(String... url) { return result; } @Override protected void onPostExecute(YourObject result) { // call an external function as a result parent.ReturnThreadResult(result); } }