Возвращает значение из AsyncTask в Android

Один простой вопрос: можно ли вернуть значение в AsyncTask ?

 //AsyncTask is a member class private class MyTask extends AsyncTask{ 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() 

EDIT: Это было спрошено давным-давно, когда я не был знаком с Java, теперь, когда мне будет лучше, я сделаю краткое резюме:

Точка async-задачи состоит в том, что задача является asynchronous , а это означает, что после вызова функции execute() в задаче задача запускается в streamе. Возrotation значения из asynctask было бы бессмысленным, потому что исходный stream вызовов уже выполнял другие вещи (при этом задача была асинхронной).

Подумайте о времени: в какой-то момент вы начали задачу, которая будет работать параллельно с основным streamом. Когда выполнение параллельной задачи завершено, время также продолжается по основному streamу. Параллельная задача не может вернуться во времени, чтобы вернуть значение в основной stream.

Я приехал с C, поэтому я мало что знал об этом. Но похоже, что у многих людей возникает один и тот же вопрос, поэтому я подумал, что немного разобрался.

Почему бы не вызвать метод, который обрабатывает значение?

 public class MyClass extends Activity { private class myTask extends AsyncTask { //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() . Он работает в streamе пользовательского интерфейса, и вы можете доставить свой результат оттуда на экран (или где-нибудь еще, что вам нужно). Он не будет вызываться до тех пор, пока окончательный результат не будет доступен. Если вы хотите предоставить промежуточные результаты, посмотрите на onProgressUpdate()

Самый простой способ – передать вызывающий объект в задачу async (при его построении, если хотите):

 public class AsyncGetUserImagesTask extends AsyncTask { private MyImagesPagerFragment mimagesPagerFragment; private ArrayList mImages = new ArrayList(); 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); } } 

И в вызывающем classе (ваша деятельность или fragment) выполняется задача:

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

И тогда onPostExecuteMethod вызовет любой метод в вашем исходном classе, который вам нравится, например:

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

вы можете попробовать это: myvalue = new myTask().execute().get(); минус, это заморозит процесс до тех пор, пока асинхрон не будет закончен;

Пример кода: Activity использует AsyncTask для получения значения в фоновом streamе, затем AsyncTask возвращает результат обратно в Activity, вызывая processValue:

 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 { @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); } } } 

Вам необходимо использовать «протоколы» для делегирования или предоставления данных в AsynTask .

Делегаты и источники данных

Делегат – это объект, который действует от имени или в координации с другим объектом, когда этот объект встречает событие в программе. ( Определение Apple )

протоколы – это интерфейсы, которые определяют некоторые методы делегирования некоторых действий.


DELEGATE : вырезать события из объекта в фоновом streamе


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... @Override void onTaskEndWithResult(int success) { } //handle data to show them in activity... @Override void onTaskFinishGettingData(Data result) { } } 

EDIT: если вы вызываете делегата в doInBackground, и делегат попытается отредактировать какое-то представление, это приведет к сбою, потому что представление может управляться только основным streamом.


EXTRA

DATASOURCE: предоставление данных объекту в фоновом streamе


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... @Override Object objectAtIndex(int index) { return new Data(index); } //send more information... @Override int indexOfObject(Object object) { return new object.getIndex(); } } 

Использовать общие параметры

 AsyncTask 
  • Params – тип входных данных задачи
  • Progress – как информировать мир о прогрессе
  • Result – тип выходных данных задачи

Подумайте как

 Result = task(Params) 

пример

Загрузите свой YourObject помощью строки URL:

 new AsyncTask() { @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/"); 

Для получения результата от 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... 

У меня была проблема с использованием .get() из AsyncTask, и ProgressBar просто не работает с get() , на самом деле, он работает только после завершения makeInBackground.

Надеюсь, это поможет вам.

Передайте MainActivity classу Async, поэтому вы получите доступ к функциям MainActivity во внутреннем classе. Это отлично работает для меня:

 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 { 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); } } 
  • Не запрашивать проблему Window.FEATURE_ACTION_BAR
  • декомпиляция DEX в исходный код Java
  • Не удалось импортировать новый проект Gradle: не удалось найти версию Build Tools * .0.0
  • Android SQLite и огромные наборы данных
  • Как запустить одновременно два метода
  • Как изменить стиль TextView во время выполнения
  • Theme.AppCompat.Light.DarkActionBar - Ресурс не найден
  • IDEA: javac: исходный релиз 1.7 требует целевого релиза 1.7
  • Integer.toString (int i) vs String.valueOf (int i)
  • Проверка сертификатов X509 с использованием Java APis
  • Разрешение на запись на SD-карту
  • Давайте будем гением компьютера.