Come ottenere il risultato di OnPostExecute () nell'attività principale perché AsyncTask è una classe separata?


362

Ho queste due lezioni. La mia attività principale e quella che estende il AsyncTask, Ora nella mia attività principale ho bisogno di ottenere il risultato dal OnPostExecute()in AsyncTask. Come posso passare o ottenere il risultato per la mia attività principale?

Ecco i codici di esempio.

La mia attività principale.

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

}

Questa è la 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);

}       

}   

È possibile creare un'interfaccia come spiegato da HelmiB oppure è possibile creare un ricevitore di trasmissione locale È possibile vedere l'implementazione del ricevitore di trasmissione di esempio qui wiki.workassis.com/android-local-broadcast-receiver
Bikesh M

Perché non usare il modello Observer?
JAAAY,

Risposte:


751

Facile:

  1. Crea interfaceclasse, dove String outputè facoltativo, o può essere qualsiasi variabile tu voglia restituire.

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
  2. Vai alla tua AsyncTaskclasse e dichiara l'interfaccia AsyncResponsecome un campo:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
  3. Nella tua attività principale devi implementsinterfacciarti 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.
       }
     }
    

AGGIORNARE

Non sapevo che questo è un favorito per molti di voi. Quindi ecco il modo semplice e conveniente da usare interface.

usando ancora lo stesso interface. Cordiali saluti, è possibile combinare questo in AsyncTaskclasse.

in AsyncTaskclasse:

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

fallo nella tua 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();

 }

In alternativa, implementare nuovamente l'interfaccia sull'attività

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.
    }
}

Come puoi vedere 2 soluzioni sopra, la prima e la terza, è necessario creare il metodo processFinish, l'altro, il metodo è all'interno del parametro caller. Il terzo è più pulito perché non esiste una classe anonima nidificata. Spero che sia di aiuto

Suggerimento : cambia String output, String responsee String resultin diversi tipi di corrispondenza per ottenere oggetti diversi.


20
Totalmente scritto tutto e poi ho visto la tua risposta :) Ecco a pensare allo stesso modo! +1. Anche in questo modo più cose possono ascoltare i risultati di AsyncTask!
Roloc,

8
Ricevo un'eccezione nullpointer perché il delegato è impostato su null, per favore chiariscilo
Reyjohn,

2
Solo una nota per gli sviluppatori .net, si può usare AutoResetEvents per raggiungere questo obiettivo e c'è anche un'implementazione java per gli autoresetevents ma questo è molto più pulito. A proposito, il thread ProcessFinish è sicuro?
Syler,

13
per tutti coloro che ottengono un puntatore nullo passare la propria interfaccia al costruttore della classe asyncTask, quindi assegnarla a una variabile e quindi chiamare processfinish () su quella variabile. Per riferimento vedi risposta accettata. stackoverflow.com/questions/9963691/…
Sunny

2
@Sunny hai ragione ... inoltre, dobbiamo inizializzare l'oggetto asincrono per async.delegate = this; per lavorare ..
Ninja_Coder

24

Ci sono alcune opzioni:

  • Nidifica la AsyncTaskclasse all'interno della tua Activityclasse. Supponendo che non si usi la stessa attività in più attività, questo è il modo più semplice. Tutto il codice rimane invariato, basta spostare la classe di attività esistente in una classe nidificata all'interno della classe della tua attività.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
    
  • Crea un costruttore personalizzato per il tuo AsyncTaskche faccia riferimento al tuo Activity. Avresti un'istanza dell'attività con qualcosa del genere 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
        ...
    }
    

Nella seconda opzione: perché passare attraverso il dolore di un costruttore e di un campo se la classe non lo è static? Basta usare qualsiasi fieldOrMethodda MyActivityo MyActivity.this.fieldOrMethodse è in ombra.
TWiStErRob,

@TWiStErRob La seconda assume MyAsyncTaskè non una classe interna.
quietmint

1
Oh, scusa, private/ protectedper le classi di livello superiore non è permesso, quindi ho pensato che dovesse essere una staticclasse non interna.
TWiStErRob,

2
Fai solo attenzione che la classe interna AsyncTask possa essere una fonte di perdite di memoria, come spiegato qui garena.github.io/blog/2014/09/10/android-memory-leaks
Mark Pazon

2
Trattenersi su un riferimento di attività è anche una perdita di memoria. L'approccio di callback è molto meglio di questo
OneCricketeer,

19

Ho sentito che l'approccio di seguito è molto semplice.

Ho dichiarato un'interfaccia per il callback

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

Quindi ha creato un'attività asincrona per rispondere a tutti i tipi di richieste parallele

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

}

Quindi ha chiamato l'attività asincrona quando si fa clic su un pulsante nella classe di attività.

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.." });


            }
        });

    }



}

Grazie


17

Puoi provare questo codice nella tua classe principale. Ha funzionato per me, ma ho implementato metodi in altro modo

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}

2
Puoi spiegare perché questo aiuterebbe l'OP a risolvere il problema?
John Odom,

3
Questo mi ha aiutato. Ho provato in un altro modo come la risposta di @HelmiB ma non ottengo risultati
Nicu P

Ok scusa per la mia risposta. Deve chiamare la classe AsyncTask e quindi inserire un parametro per questa chiamata. AsyncTask è definito da 3 tipi generici: 1 parametro (dominio del server o altro parametro) 2 avanzamento (può essere nullo), 3 risultati. Tutti questi tipi possono essere: JSONObject o stringhe o qualsiasi tipo di dati. Quando si dispone di una classe AsyncTask, è necessario definire dove inviare i dati. es: asyncTask.execute (" sampletargeturl.com"). get () ;
Nicu P,

Quando si utilizza questo metodo, ho ricevuto un avviso su Logcat: "I / Choreographer ﹕ ha saltato 50 frame! L'applicazione potrebbe fare troppo lavoro sul suo thread principale." Come gestirlo? L'interfaccia utente viene bloccata durante l'attesa di ritorno da AsyncTask?
Huy Do,

@NicuP potresti aver dimenticato di chiamare execute(), vedi la mia risposta, ho aggiunto un commento lì. potresti voler controllare la mia risposta aggiornata. spero che sia di aiuto.
HelmiB,

16

Questa risposta potrebbe essere in ritardo, ma vorrei menzionare alcune cose quando sei Activitydipendente AsyncTask. Ciò ti aiuterebbe a prevenire arresti anomali e gestione della memoria. Come già accennato nelle risposte precedenti interface, diciamo anche loro richiamate. Funzioneranno come informatore, ma non invieranno mai riferimenti fortiActivity o interfaceutilizzeranno sempre riferimenti deboli in questi casi.

Fare riferimento allo screenshot seguente per scoprire come ciò può causare problemi.

inserisci qui la descrizione dell'immagine

Come puoi vedere se abbiamo iniziato AsyncTaskcon un forte riferimento, non esiste alcuna garanzia che il nostro Activity/ Fragmentsarà attivo fino a quando non avremo i dati, quindi sarebbe meglio usare WeakReferencein quei casi e ciò aiuterà anche nella gestione della memoria poiché non terremo mai il forte riferimento del nostro Activityallora sarà ammissibile alla raccolta dei rifiuti dopo la sua distorsione.

Controlla lo snippet di codice qui sotto per scoprire come usare WeakReference impressionante -

MyTaskInformer.java Interfaccia che funzionerà come informatore.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.javaAsyncTask per eseguire attività di lunga durata, che utilizzerà 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.javaQuesta classe viene utilizzata per iniziare la mia AsyncTaskimplementare interfacesu questa classe e overridequesto metodo obbligatorio.

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

2
Questo è fantastico! un punto importante che non si può notare.
HasH il

6

nel tuo 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();

} `


6

Puoi farlo in poche righe, basta ignorare PostExecute quando chiami AsyncTask. Ecco un esempio per te:

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

Spero che ti abbia aiutato, felice codding :)


Non funziona per me. Semplicemente non entra nel onPostExecutemetodo.
Francisco Romero,

4

Perché le persone lo rendono così difficile.

Questo dovrebbe essere sufficiente.

Non implementare onPostExecute sull'attività asincrona, piuttosto implementarlo sull'attività:

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");

}


}

Questo funziona per me. È il più semplice e il più facile da capire. Penso che stia facendo uso di ciò che Java è progettato per fare. Grazie. PS: è necessario aggiungere un @Override?
Old Geezer,

1
No. @Override è solo un'annotazione. Quindi stai dicendo al compilatore Java che hai intenzione di sovrascrivere il metodo e di informarti se non lo stai facendo.
bugdayci,

4

È possibile chiamare il get()metodo di AsyncTask(o sovraccarico get(long, TimeUnit)). Questo metodo bloccherà fino a quando non AsyncTaskavrà completato il suo lavoro, a quel punto ti restituirà il Result.

Sarebbe saggio fare altro lavoro tra la creazione / avvio dell'attività asincrona e la chiamata del getmetodo, altrimenti non si sta utilizzando l'attività asincrona in modo molto efficiente.


1
Downvoted perché get () bloccherà il thread principale. Nessun motivo per utilizzare AsyncTask se bloccherà
GabrielBB

3

Puoi scrivere il tuo ascoltatore. È uguale alla risposta di HelmiB ma sembra più naturale:

Crea interfaccia listener:

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

Quindi scrivi l'attività asincrona:

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

Infine implementare l'ascoltatore nell'attività:

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
        }        
    }

Ed è così che puoi chiamare 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...
}

2

Ciao puoi fare qualcosa del genere:

  1. Crea una classe che 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. Aggiungi in Attività principale

    // 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();
       ...
     }

1

Crea un membro statico nella tua classe Activity. Quindi assegnare il valore durante ilonPostExecute

Ad esempio, se il risultato di AsyncTask è una stringa, crea una stringa statica pubblica nella tua attività

public static String dataFromAsyncTask;

Quindi, in onPostExecuteAsyncTask, effettua semplicemente una chiamata statica alla tua classe principale e imposta il valore.

MainActivity.dataFromAsyncTask = "result blah";


1
quali sono le possibilità di perdita di memoria in questo scenario?
antroid

0

Lo faccio funzionare usando threading e handler / message. Passaggi come segue: dichiarare una finestra di avanzamento

ProgressDialog loadingdialog;

Creare una funzione per chiudere la finestra di dialogo al termine dell'operazione.

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

    }
    };

Codifica i dettagli dell'esecuzione:

 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();
}

0

È necessario utilizzare "protocolli" per delegare o fornire dati a AsynTask.

Delegati e fonti di dati

Un delegato è un oggetto che agisce per conto o in coordinamento con un altro oggetto quando quell'oggetto incontra un evento in un programma. ( Definizione di Apple )

i protocolli sono interfacce che definiscono alcuni metodi per delegare alcuni comportamenti.

Ecco un esempio completo !!!


0

prova questo:

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 esempio di utilizzo:

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");

    }

0

Probabilmente esagerando un po ', ma ho fornito richiamate sia per il codice di esecuzione che per i risultati. ovviamente per la sicurezza del thread vuoi stare attento a ciò a cui accedi nel tuo callback di esecuzione.

L'implementazione di 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);
    }
}

Un callback:

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

E infine l'esecuzione dell'attività asincrona:

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

0

Spero che tu abbia superato questo , se no, per favore leggi.

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

A seconda della natura dei dati dei risultati, è necessario scegliere la migliore opzione possibile.

Si tratta di una grande scelta di utilizzare un interfaccia

alcune altre opzioni sarebbero ..

  • Se la classe AsyncTask è definita all'interno della stessa classe in cui si desidera utilizzare il risultato. Utilizzare una variabile globale statica o get () , utilizzarla dalla classe esterna ( variabile volatile se necessario). ma dovrebbe essere a conoscenza del AsyncTask progressi o dovrebbe almeno assicurarsi che hanno finito il compito e il risultato è disponibile attraverso il metodo variabile globale / get (). puoi utilizzare polling, onProgressUpdate (Progress ...) , sincronizzazione o interfacce (che si adatta meglio a te)

  • Se il risultato è compatibile per essere una voce sharedPreference o va bene essere salvato come file nella memoria, è possibile salvarlo anche dall'attività in background stessa e utilizzare il metodo onPostExecute ()
    per ricevere una notifica quando il risultato è disponibile in la memoria.

  • Se la stringa è abbastanza piccola e deve essere utilizzata con l'inizio di un'attività. è possibile utilizzare gli intenti ( putExtra () ) entro OnPostExecute () , ma ricordate che i contesti statici non sono così sicuri da affrontare.

  • Se possibile, è possibile chiamare un metodo statico dal metodo onPostExecute (), con il risultato come parametro

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.