Общий класс AsyncTask для Android

Я видел этот ответ: Как получить результат OnPostExecute() для основной активности, потому что AsyncTask - это отдельный класс?

Но это не то, что я прошу, поскольку мой вызывающий класс имеет несколько вызовов для AsyncTask.

Я хочу создать общий AsyncTask класс, который будет принимать URL-адрес и загружать контент из заданного URL-адреса и возвращать загруженный контент.

Пример:

public class MyAsyncTask extends AsyncTask<String, Void, String>{
    ProgressDialog dialog;

    protected void onPreExecute() {
        super.onPreExecute();
        dialog = ProgressDialog.show(context, "Loading", "Please wait...", true);
    }

    protected String doInBackground(String... params) {
        // do download here
    }

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        dialog.dismiss();
    }
}

И у меня есть другой класс, который вызывает этот AsyncTask в разных сценариях

public class MyClass {

    public method1(String url) {
        String result = new MyAsyncTask().execute(url).get();
    }

    public method2(String url) {
        String result = new MyAsyncTask().execute(url).get();
    }
}

Я знаю, что использование метода get() сделает весь этот процесс задачей синхронизации. Но я хочу вернуть результат в вызывающий класс. И я также знаю, чтобы предотвратить это, я должен реализовать интерфейс. Но поскольку у меня есть несколько вызовов в одном классе, это невозможно. Так может ли кто-нибудь дать мне идею решить эту проблему?

Ответы

Ответ 1

Поскольку doInBackground работает в фоновом режиме, вы не можете получить результат в нем, возвращая значение при вызове из активности.

Вам нужно установить обратный вызов, который будет вызван с результатом.

Для ex:

interface Callback{
void onResult(String result);
}

Сделайте свою деятельность реализацией этого и в действии

void onResult(String result){
    //Do something
}

Теперь измените ваш asyncTask на:

public class MyAsyncTask extends AsyncTask<String, Void, String>{

   ProgressDialog dialog;
   Callback callback;
public MyAsyncTask(Callback callback){
 this.callback=callback;
}
protected void onPreExecute() {
    super.onPreExecute();
    dialog = ProgressDialog.show(context, "Loading", "Please wait...", true);
}

protected String doInBackground(String... params) {
    //do download here
}

protected void onPostExecute(String result) {
    super.onPostExecute(result);
    callback.onResult(result);
    dialog.dismiss();
}
} 

Во время запуска этой задачи из действия:

 new MyAsyncTask(new Callback{
void onResult(String result){ 
 //Do something
}
}).execute(url);

Поэтому, когда вы получите ответ onResult, вызывается

Ответ 2

Почему несколько вызовов в одном классе нарушают интерфейс?

class Task extends AsyncTask{

    public interface TaskDoneListener{
        public void onDone(String result);
    }

    private TaskDoneListener listener;
    public Task(TaskDoneListener list){
        super();
        listener = list;
    }

    public void onPostExecute(String result){
        listener.onDone(result);
    }
}

Ответ 3

Я предлагаю вам создать класс abstract для этого:

public abstract class AsyncDownloader extends AsyncTask<...> {
    doInBackground(Params...){
        return doNetworkDownload();
    }
    ABSTRACK onPostExecute(Result);// Notice there no method body
}

Затем в любой из ваших действий, где задача загрузки одинакова, но разбор отличается, расширьте этот класс:

public class MainActivityAsyncTask extends AsyncDownloader {
    //It will give you error, that you must implement the onPostExecute method at first
    @Override
    onPostExecute(Result){
        doUiStuff();
    }
}

Ответ 4

В вашем классе переопределите onPostExecute, чтобы вернуть результат в ваш класс.

MyAsyncTask mytask = new MyAsyncTask(){
    @Override
    protected void onPostExecute(String result) {
        //your code
    }
}
mytask.execute(url);

Ответ 5

Вам нужно будет сделать интерфейс и в этом интерфейсе добавить один метод, имеющий тип аргумента, который вы хотите вернуть из AsyncTask.

и в конструкторе ссылки интерфейса интерфейса AsyncTask из вашей активности. и установить данные в интерфейсном методе из onPostExecute().

поэтому вы будете уведомлены в классе активности, если данные установлены из метода onPostExecute.

следуйте этому приятному ответу fooobar.com/info/9511/...