Como obter o resultado de OnPostExecute () para a atividade principal porque o AsyncTask é uma classe separada?

361

Eu tenho essas duas aulas. Minha Atividade principal e a que estende o AsyncTaskAgora, na minha Atividade principal, preciso obter o resultado do OnPostExecute()no AsyncTask. Como posso passar ou obter o resultado para minha Atividade principal?

Aqui estão os códigos de amostra.

Minha atividade principal.

public class MainActivity extends Activity{

    AasyncTask asyncTask = new AasyncTask();

    @Override
    public void onCreate(Bundle aBundle) {
        super.onCreate(aBundle);            

        //Calling the AsyncTask class to start to execute.  
        asyncTask.execute(a.targetServer); 

        //Creating a TextView.
        TextView displayUI = asyncTask.dataDisplay;
        displayUI = new TextView(this);
        this.setContentView(tTextView); 
    }

}

Esta é a classe AsyncTask

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

TextView dataDisplay; //store the data  
String soapAction = "http://sample.com"; //SOAPAction header line. 
String targetServer = "https://sampletargeturl.com"; //Target Server.

//SOAP Request.
String soapRequest = "<sample XML request>";    



@Override
protected String doInBackground(String... string) {

String responseStorage = null; //storage of the response

try {


    //Uses URL and HttpURLConnection for server connection. 
    URL targetURL = new URL(targetServer);
    HttpURLConnection httpCon = (HttpURLConnection) targetURL.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setDoInput(true);
    httpCon.setUseCaches(false); 
    httpCon.setChunkedStreamingMode(0);

    //properties of SOAPAction header
    httpCon.addRequestProperty("SOAPAction", soapAction);
    httpCon.addRequestProperty("Content-Type", "text/xml; charset=utf-8"); 
    httpCon.addRequestProperty("Content-Length", "" + soapRequest.length());
    httpCon.setRequestMethod(HttpPost.METHOD_NAME);


    //sending request to the server.
    OutputStream outputStream = httpCon.getOutputStream(); 
    Writer writer = new OutputStreamWriter(outputStream);
    writer.write(soapRequest);
    writer.flush();
    writer.close();


    //getting the response from the server
    InputStream inputStream = httpCon.getInputStream(); 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);

    int intResponse = httpCon.getResponseCode();

    while ((intResponse = bufferedReader.read()) != -1) {
        byteArrayBuffer.append(intResponse);
    }

    responseStorage = new String(byteArrayBuffer.toByteArray()); 

    } catch (Exception aException) {
    responseStorage = aException.getMessage(); 
    }
    return responseStorage;
}

protected void onPostExecute(String result) {

    aTextView.setText(result);

}       

}   
Stella
fonte
Você pode criar uma interface como HelmiB explicado ou você pode criar uma transmissão local receptor Você pode ver a amostra implementação transmissão reciver aqui wiki.workassis.com/android-local-broadcast-receiver
Bikesh M
Por que não usar o padrão Observer?
JAAAY

Respostas:

750

Fácil:

  1. Crie uma interfaceclasse, onde String outputé opcional, ou pode ser qualquer variável que você deseja retornar.

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
  2. Vá para a sua AsyncTaskturma e declare a interface AsyncResponsecomo um campo:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
  3. Na sua atividade principal, você precisa fazer a implementsinterface AsyncResponse.

    public class MainActivity implements AsyncResponse{
      MyAsyncTask asyncTask =new MyAsyncTask();
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
    
         //this to set delegate/listener back to this class
         asyncTask.delegate = this;
    
         //execute the async task 
         asyncTask.execute();
      }
    
      //this override the implemented method from asyncTask
      @Override
      void processFinish(String output){
         //Here you will receive the result fired from async class 
         //of onPostExecute(result) method.
       }
     }
    

ATUALIZAR

Eu não sabia que isso é o favorito de muitos de vocês. Então, aqui está a maneira simples e conveniente de usar interface.

ainda usando o mesmo interface. Para sua informação, você pode combinar isso em AsyncTaskclasse.

na AsyncTaskaula:

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

  // you may separate this or combined to caller class.
  public interface AsyncResponse {
        void processFinish(String output);
  }

  public AsyncResponse delegate = null;

    public MyAsyncTask(AsyncResponse delegate){
        this.delegate = delegate;
    }

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

faça isso na sua Activityclasse

public class MainActivity extends Activity {

   MyAsyncTask asyncTask = new MyAsyncTask(new AsyncResponse(){

     @Override
     void processFinish(String output){
     //Here you will receive the result fired from async class 
     //of onPostExecute(result) method.
     }
  }).execute();

 }

Ou, implementando a interface na Atividade novamente

public class MainActivity extends Activity 
    implements AsyncResponse{

    @Override
    public void onCreate(Bundle savedInstanceState) {

        //execute the async task 
        new MyAsyncTask(this).execute();
    }

    //this override the implemented method from AsyncResponse
    @Override
    void processFinish(String output){
        //Here you will receive the result fired from async class 
        //of onPostExecute(result) method.
    }
}

Como você pode ver 2 soluções acima, a primeira e a terceira, ela precisa criar o método processFinish, a outra, o método está dentro do parâmetro do chamador. A terceira é mais organizada porque não há classe anônima aninhada. Espero que isto ajude

Dica : Mudança String output, String responsee String resultpara diferentes tipos de correspondência, a fim de obter diferentes objetos.

HelmiB
fonte
20
Totalmente escrevi tudo isso e depois vi sua resposta :) Vamos pensar da mesma forma! +1. Além disso, desta maneira, várias coisas podem ouvir os resultados do AsyncTask!
Roloc
8
Estou ficando exceção nullpointer porque delegado é definido como nulo, por favor clearify-lo
Reyjohn
2
Apenas uma observação para os desenvolvedores .net, pode-se usar o AutoResetEvents para conseguir isso e também há uma implementação em java para os autoresetevents, mas isso é muito mais limpo. A propósito, o thread ProcessFinish é seguro?
quer
13
para todos aqueles que estão recebendo ponteiro nulo, passe sua interface para o construtor de classe asyncTask, atribua-a a uma variável e chame processfinish () nessa variável. Para referência, consulte aceito. stackoverflow.com/questions/9963691/…
Sunny
2
@ Sunny você está certo ... também, temos que inicializar o objeto assíncrono para async.delegate = this; para trabalhar ..
Ninja_Coder 29/07
24

Existem algumas opções:

  • Aninhe a AsyncTaskclasse dentro da sua Activityclasse. Supondo que você não use a mesma tarefa em várias atividades, essa é a maneira mais fácil. Todo o seu código permanece o mesmo, basta mover a classe de tarefa existente para uma classe aninhada dentro da classe da sua atividade.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
  • Crie um construtor personalizado para o seu AsyncTaskque faça referência ao seu Activity. Você instanciaria a tarefa com algo parecido new MyAsyncTask(this).execute(param1, param2).

    public class MyAsyncTask extends AsyncTask<String, Void, String> {
        private Activity activity;
    
        public MyAsyncTask(Activity activity) {
            this.activity = activity;
        }
    
        // existing AsyncTask code
        ...
    }
quietmint
fonte
Na segunda opção: Por que passar pela dor de um construtor e de um campo se a classe não é static? Basta usar qualquer fieldOrMethodde MyActivityou MyActivity.this.fieldOrMethodse é sombreada.
TWIStErRob
@TWiStErRob O segundo assume que nãoMyAsyncTask é uma classe interna.
23915 quietmint
11
Ah, desculpe, private/ protectedpara as classes de nível superior não é permitido, portanto, pensei que deveria ser uma staticclasse não interna.
TWiStErRob 23/02
2
Basta ter cuidado que interna classe AsyncTask pode ser uma fonte de vazamentos de memória como explicado aqui garena.github.io/blog/2014/09/10/android-memory-leaks
Mark Pazon
2
Manter uma referência de atividade também é um vazamento de memória. A abordagem de retorno de chamada é muito melhor do que isso
OneCricketeer
19

Eu senti a abordagem abaixo é muito fácil.

Eu declarei uma interface para retorno de chamada

public interface AsyncResponse {
    void processFinish(Object output);
}

Tarefa assíncrona criada para responder a todos os tipos de solicitações paralelas

 public class MyAsyncTask extends AsyncTask<Object, Object, Object> {

    public AsyncResponse delegate = null;//Call back interface

    public MyAsyncTask(AsyncResponse asyncResponse) {
        delegate = asyncResponse;//Assigning call back interfacethrough constructor
    }

    @Override
    protected Object doInBackground(Object... params) {

      //My Background tasks are written here

      return {resutl Object}

    }

    @Override
    protected void onPostExecute(Object result) {
        delegate.processFinish(result);
    }

}

Em seguida, chamou a tarefa assíncrona ao clicar em um botão na atividade Classe.

public class MainActivity extends Activity{

    @Override
    public void onCreate(Bundle savedInstanceState) {

    Button mbtnPress = (Button) findViewById(R.id.btnPress);

    mbtnPress.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {

                    @Override
                    public void processFinish(Object output) {
                        Log.d("Response From Asynchronous task:", (String) output);

                        mbtnPress.setText((String) output);
                   }
                });

                asyncTask.execute(new Object[] { "Your request to aynchronous task class is giving here.." });


            }
        });

    }



}

obrigado

Arshad
fonte
17

Você pode tentar esse código na sua classe principal. Isso funcionou para mim, mas eu implementei métodos de outra maneira

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}
Nicu P
fonte
2
Você pode explicar por que isso ajudaria o OP com o problema deles?
John Odom 27/05
3
Isso me ajudou. Eu tentei de outra maneira como a resposta do @HelmiB mas eu não obter nenhum resultado
Nicu P
Ok, desculpe pela minha resposta. Ela precisa chamar a classe AsyncTask e, em seguida, colocar um parâmetro nessa chamada. O AsyncTask é definido por 3 tipos genéricos: 1 parâmetro (domínio do servidor ou outro parâmetro) 2 progresso (pode ser nulo), 3 resultado. Todos esses tipos podem ser: JSONObject, ou strings, ou qualquer tipo de dados. Quando você tem uma classe AsyncTask, deve definir para onde enviar os dados. ex: asyncTask.execute (" sampletargeturl.com"). get () ;
Nicu P
Ao usar esse método, recebi um aviso no Logcat: "I / Choreographer ﹕ Ignorou 50 quadros! O aplicativo pode estar fazendo muito trabalho em seu encadeamento principal." Como lidar com isso? A interface do usuário fica congelada ao aguardar o retorno do AsyncTask?
Huy Do
@ NicuP você pode ter esquecido de ligar execute(), veja minha resposta, eu adicionei um comentário lá. convém verificar minha resposta atualizada. espero que isto ajude.
HelmiB 4/15/15
16

Esta resposta pode estar atrasada, mas eu gostaria de mencionar algumas coisas quando você Activitydepende AsyncTask. Isso ajudaria você a evitar falhas e gerenciamento de memória. Como já mencionado nas respostas acima interface, também os chamamos de retorno de chamada. Eles funcionarão como informantes, mas nunca enviarão uma referência forteActivity ou interfacesempre usarão uma referência fraca nesses casos.

Consulte a captura de tela abaixo para descobrir como isso pode causar problemas.

insira a descrição da imagem aqui

Como você pode ver se começamos AsyncTaskcom uma referência forte , não há garantia de que nosso Activity/ Fragmentestará vivo até obtermos dados; portanto, seria melhor usá WeakReference-lo nesses casos e que também ajudará no gerenciamento de memória, pois nunca manteremos a forte referência de nossa Activityentão será elegível para coleta de lixo após sua distorção.

Verifique o trecho de código abaixo para descobrir como usar o WeakReference incrível -

MyTaskInformer.java Interface que funcionará como um informador.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.javaAsyncTask para executar tarefas de longa duração, que serão usadas WeakReference.

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

    // ***** Hold weak reference *****
    private WeakReference<MyTaskInformer> mCallBack;

    public MySmallAsyncTask(MyTaskInformer callback) {
        this.mCallBack = new WeakReference<>(callback);
    }

    @Override
    protected String doInBackground(String... params) {

        // Here do whatever your task is like reading/writing file
        // or read data from your server or any other heavy task

        // Let us suppose here you get response, just return it
        final String output = "Any out, mine is just demo output";

        // Return it from here to post execute
        return output;
    }

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

        // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask

        // Make sure your caller is active

        final MyTaskInformer callBack = mCallBack.get();

        if(callBack != null) {
            callBack.onTaskDone(s);
        }
    }
}

MainActivity.javaEsta classe é usada para iniciar meu AsyncTaskimplemento interfacenesta classe e overrideneste método obrigatório.

public class MainActivity extends Activity implements MyTaskInformer {

    private TextView mMyTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMyTextView = (TextView) findViewById(R.id.tv_text_view);

        // Start your AsyncTask and pass reference of MyTaskInformer in constructor
        new MySmallAsyncTask(this).execute();
    }

    @Override
    public void onTaskDone(String output) {

        // Here you will receive output only if your Activity is alive.
        // no need to add checks like if(!isFinishing())

        mMyTextView.setText(output);
    }
}
Rahul
fonte
2
Isso é ótimo! um ponto importante que não pode ser percebido.
HasH
6

no seu Oncreate ():

`

myTask.execute("url");
String result = "";
try {
      result = myTask.get().toString();
} catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
}catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();

} `

user3691697
fonte
6

Você pode fazer isso em poucas linhas, substituindo onPostExecute ao chamar sua AsyncTask. Aqui está um exemplo para você:

new AasyncTask()
{
    @Override public void onPostExecute(String result)
    {
       // do whatever you want with result 
    }
}.execute(a.targetServer);

Espero que tenha ajudado, codificação feliz :)

Ayaz Alifov
fonte
Isso não funciona para mim. Apenas não entra no onPostExecutemétodo.
Francisco Romero
4

Por que as pessoas tornam isso tão difícil?

Isso deve ser suficiente.

Não implemente o onPostExecute na tarefa assíncrona; em vez disso, implemente-o na atividade:

public class MainActivity extends Activity 
{

@Override
public void onCreate(Bundle savedInstanceState) {

    //execute the async task 
    MyAsyncTask task = new MyAsyncTask(){
            protected void onPostExecute(String result) {
                //Do your thing
            }       

    }

    task.execute("Param");

}


}
bugdayci
fonte
Isso funciona para mim. É o mais simples e mais fácil de entender. Eu acho que está fazendo uso do que o Java foi projetado para fazer. Obrigado. PS: É necessário adicionar um @Override?
Old Geezer
11
Não. @ Substituir é apenas uma anotação. Então, você está dizendo ao compilador java que pretende substituir o método e ser informado se não estiver fazendo isso.
Bugdayci
4

Você pode chamar o get()método de AsyncTask(ou sobrecarregado get(long, TimeUnit)). Esse método será bloqueado até que o trabalho AsyncTaskseja concluído e, nesse momento, ele retornará o Result.

Seria sensato fazer outro trabalho entre a criação / início da tarefa assíncrona e chamar o getmétodo, caso contrário, você não está utilizando a tarefa assíncrona com muita eficiência.

nicholas.hauschild
fonte
11
Voto negativo, porque get () bloqueará o thread principal. Não há razão para usar AsyncTask se ele vai bloquear
GabrielBB
3

Você pode escrever seu próprio ouvinte. É o mesmo que a resposta de HelmiB , mas parece mais natural:

Crie uma interface de ouvinte:

public interface myAsyncTaskCompletedListener {
    void onMyAsynTaskCompleted(int responseCode, String result);
}

Em seguida, escreva sua tarefa assíncrona:

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

    private myAsyncTaskCompletedListener listener;
    private int responseCode = 0;

    public myAsyncTask() {
    }

    public myAsyncTask(myAsyncTaskCompletedListener listener, int responseCode) {
        this.listener = listener;
        this.responseCode = responseCode;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }


    @Override
    protected String doInBackground(String... params) {
        String result;
        String param = (params.length == 0) ? null : params[0];
        if (param != null) {
            // Do some background jobs, like httprequest...
            return result;
        }
        return null;
    }

    @Override
    protected void onPostExecute(String finalResult) {
        super.onPostExecute(finalResult);
        if (!isCancelled()) {
            if (listener != null) {
                listener.onMyAsynTaskCompleted(responseCode, finalResult);
            }
        }
    }
}

Por fim, implemente o ouvinte na atividade:

public class MainActivity extends AppCompatActivity implements myAsyncTaskCompletedListener {

    @Override
    public void onMyAsynTaskCompleted(int responseCode, String result) {

        switch (responseCode) {
            case TASK_CODE_ONE: 
                // Do something for CODE_ONE
                break;
            case TASK_CODE_TWO:
                // Do something for CODE_TWO
                break;
            default: 
                // Show some error code
        }        
    }

E é assim que você pode chamar asyncTask:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Some other codes...
        new myAsyncTask(this,TASK_CODE_ONE).execute("Data for background job");
        // And some another codes...
}
Kuvalya
fonte
2

Oi, você pode fazer algo parecido com isto:

  1. Criar classe que implementa AsyncTask

    // TASK 
    public class SomeClass extends AsyncTask<Void, Void, String>>
    {
    
        private OnTaskExecutionFinished _task_finished_event;
    
        public interface OnTaskExecutionFinished
        {
            public void OnTaskFihishedEvent(String Reslut);
        }
    
        public void setOnTaskFinishedEvent(OnTaskExecutionFinished _event)
        {
            if(_event != null)
            {
                this._task_finished_event = _event;
            }
        }
    
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
    
        }
    
        @Override
        protected String doInBackground(Void... params)
        {
            // do your background task here ...
    
            return "Done!";
        }
    
        @Override
        protected void onPostExecute(String result)
        {
            super.onPostExecute(result);
            if(this._task_finished_event != null)
            {
                this._task_finished_event.OnTaskFihishedEvent(result);
            }
            else
            {
                Log.d("SomeClass", "task_finished even is null");
            }
        }
    }
  2. Adicionar na Atividade Principal

    // MAIN ACTIVITY
    public class MyActivity extends ListActivity
    {
       ...
        SomeClass _some_class = new SomeClass();
        _someclass.setOnTaskFinishedEvent(new _some_class.OnTaskExecutionFinished()
        {
        @Override
        public void OnTaskFihishedEvent(String result)
        {
            Toast.makeText(getApplicationContext(),
                    "Phony thread finished: " + result,
                    Toast.LENGTH_SHORT).show();
        }
    
       });
       _some_class.execute();
       ...
     }
Oleg Karbushev
fonte
1

Crie um membro estático na sua classe Activity. Em seguida, atribua o valor durante oonPostExecute

Por exemplo, se o resultado do seu AsyncTask for uma String, crie uma string estática pública em sua Activity

public static String dataFromAsyncTask;

Em seguida, no onPostExecuteAsyncTask, faça uma chamada estática para sua classe principal e defina o valor.

MainActivity.dataFromAsyncTask = "result blah";

mrres1
fonte
11
quais são as possibilidades de vazamento de memória nesse cenário?
Antroid 18/05/19
0

Eu faço funcionar usando encadeamento e manipulador / mensagem. Etapas a seguir: Declarar um diálogo de progresso

ProgressDialog loadingdialog;

Crie uma função para fechar o diálogo quando a operação estiver concluída.

   private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        loadingdialog.dismiss();

    }
    };

Codifique os detalhes da sua execução:

 public void startUpload(String filepath) {
    loadingdialog = ProgressDialog.show(MainActivity.this, "Uploading", "Uploading Please Wait", true);
    final String _path = filepath;
    new Thread() {
        public void run() {
            try {
                UploadFile(_path, getHostName(), getPortNo());
                handler.sendEmptyMessage(0);

            } catch (Exception e) {
                Log.e("threadmessage", e.getMessage());
            }
        }
    }.start();
}
RAIO
fonte
0

Você precisa usar "protocolos" para delegar ou fornecer dados para o AsynTask.

Delegados e fontes de dados

Um delegado é um objeto que age em nome ou em coordenação com outro objeto quando esse objeto encontra um evento em um programa. ( Definição da Apple )

protocolos são interfaces que definem alguns métodos para delegar alguns comportamentos.

Aqui está um exemplo completo !!!

IgniteCoders
fonte
0

tente isto:

public class SomAsyncTask extends AsyncTask<String, Integer, JSONObject> {

    private CallBack callBack;

    public interface CallBack {
        void async( JSONObject jsonResult );
        void sync( JSONObject jsonResult );
        void progress( Integer... status );
        void cancel();
    }

    public SomAsyncTask(CallBack callBack) {
        this.callBack = callBack;
    }

    @Override
    protected JSONObject doInBackground(String... strings) {

        JSONObject dataJson = null;

        //TODO query, get some dataJson

        if(this.callBack != null)
            this.callBack.async( dataJson );// asynchronize with MAIN LOOP THREAD

        return dataJson;

    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        if(this.callBack != null)
            this.callBack.progress(values);// synchronize with MAIN LOOP THREAD

    }

    @Override
    protected void onPostExecute(JSONObject jsonObject) {
        super.onPostExecute(jsonObject);

        if(this.callBack != null)
            this.callBack.sync(jsonObject);// synchronize with MAIN LOOP THREAD
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();

        if(this.callBack != null)
            this.callBack.cancel();

    }
}

E exemplo de uso:

public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         final Context _localContext = getContext();
         SomeAsyncTask.CallBack someCallBack = new SomeAsyncTask.CallBack() {

                @Override
                public void async(JSONObject jsonResult) {//async thread
                    //some async process, e.g. send data to server...
                }

                @Override
                public void sync(JSONObject jsonResult) {//sync thread
                    //get result...

                    //get some resource of Activity variable...
                    Resources resources = _localContext.getResources();
                }

                @Override
                public void progress(Integer... status) {//sync thread
                    //e.g. change status progress bar...
                }

                @Override
                public void cancel() {

                }

            };

            new SomeAsyncTask( someCallBack )
                                .execute("someParams0", "someParams1", "someParams2");

    }
amiron
fonte
0

Provavelmente exagerando um pouco, mas forneci retornos de chamada para o código de execução e os resultados. obviamente, para segurança do encadeamento, você deve ter cuidado com o que acessa no retorno de chamada de execução.

A implementação do AsyncTask:

public class AsyncDbCall<ExecuteType,ResultType> extends AsyncTask<ExecuteType, Void,  
ResultType>
{
    public interface ExecuteCallback<E, R>
    {
        public R execute(E executeInput);
    }
    public interface PostExecuteCallback<R>
    {
        public void finish(R result);
    }

    private PostExecuteCallback<ResultType> _resultCallback = null;
    private ExecuteCallback<ExecuteType,ResultType> _executeCallback = null;


    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback, PostExecuteCallback<ResultType> postExecuteCallback)
    {
        _resultCallback = postExecuteCallback;
        _executeCallback = executeCallback;
    }

    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback)
    {
        _executeCallback = executeCallback;
    }

    @Override
    protected ResultType doInBackground(final ExecuteType... params)
    {
        return  _executeCallback.execute(params[0]);
    }

    @Override
    protected void onPostExecute(ResultType result)
    {
        if(_resultCallback != null)
            _resultCallback.finish(result);
    }
}

Um retorno de chamada:

 AsyncDbCall.ExecuteCallback<Device, Device> updateDeviceCallback = new 
 AsyncDbCall.ExecuteCallback<Device, Device>()
    {
        @Override
        public Device execute(Device device)
        {
            deviceDao.updateDevice(device);
            return device;
        }
    };

E, finalmente, a execução da tarefa assíncrona:

 new AsyncDbCall<>(addDeviceCallback, resultCallback).execute(device);
Squibly
fonte
0

Espero que você tenha passado por isso , se não, leia.

https://developer.android.com/reference/android/os/AsyncTask

Dependendo da natureza dos dados do resultado, você deve escolher a melhor opção possível.

É uma ótima opção para usar um interface

algumas outras opções seriam ..

  • Se a classe AsyncTask for definida dentro da mesma classe em que você deseja usar o resultado.Use uma variável global estática ou get () , use-a da classe externa ( variável volátil, se necessário). mas deve estar ciente do progresso do AsyncTask ou, pelo menos, garantir que ela tenha concluído a tarefa e o resultado esteja disponível por meio do método global de variável / get (). você pode usar polling, onProgressUpdate (Progress ...) , sincronização ou interfaces (o que melhor lhe convier)

  • Se o resultado for compatível com uma entrada sharedPreference ou se for possível salvar como um arquivo na memória, você poderá salvá-lo mesmo da própria tarefa em segundo plano e usar o método onPostExecute ()
    para ser notificado quando o resultado estiver disponível em a memória.

  • Se a sequência for pequena o suficiente e deve ser usada com o início de uma atividade. é possível usar intenções ( putExtra () ) dentro de onPostExecute () , mas lembre-se de que contextos estáticos não são tão seguros de lidar.

  • Se possível, você pode chamar um método estático a partir do método onPostExecute (), com o resultado sendo seu parâmetro

Harsh
fonte