Bagaimana cara mendapatkan hasil OnPostExecute () ke aktivitas utama karena AsyncTask adalah kelas yang terpisah?

362

Saya punya dua kelas ini. Aktivitas utama saya dan aktivitas yang memperpanjang AsyncTask, Sekarang dalam Aktivitas utama saya, saya perlu mendapatkan hasil dari OnPostExecute()dalam AsyncTask. Bagaimana saya bisa meneruskan atau mendapatkan hasilnya ke Aktivitas utama saya?

Berikut adalah contoh kode.

Aktivitas utama saya.

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

}

Ini adalah kelas 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
sumber
Anda dapat membuat antarmuka seperti yang dijelaskan HelmiB atau Anda dapat membuat penerima siaran lokal. Anda dapat melihat contoh penerapan penerima siaran di sini wiki.workassis.com/android-local-broadcast-receiver
Bikesh M
Mengapa tidak menggunakan pola Pengamat?
JAAY

Jawaban:

751

Mudah:

  1. Buat interfacekelas, di mana String outputopsional, atau dapat berupa variabel apa pun yang ingin Anda kembalikan.

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
  2. Buka AsyncTaskkelas Anda , dan nyatakan antarmuka AsyncResponsesebagai bidang:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
  3. Dalam Aktivitas utama Anda, Anda perlu implementsantarmuka 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.
       }
     }
    

MEMPERBARUI

Saya tidak tahu ini adalah favorit bagi banyak dari Anda. Jadi, inilah cara sederhana dan nyaman untuk digunakan interface.

masih menggunakan yang sama interface. FYI, Anda dapat menggabungkan ini ke dalam AsyncTaskkelas.

di AsyncTaskkelas:

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

lakukan ini di Activitykelasmu

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

 }

Atau, mengimplementasikan antarmuka pada Kegiatan lagi

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

Seperti yang Anda lihat 2 solusi di atas, yang pertama dan ketiga, perlu membuat metode processFinish, yang lain, metode ini di dalam parameter pemanggil. Yang ketiga lebih rapi karena tidak ada kelas anonim bersarang. Semoga ini membantu

Tip : Ubah String output,, String responsedan String resultke berbagai jenis pencocokan untuk mendapatkan objek yang berbeda.

HelmiB
sumber
20
Benar-benar menulis semua itu dan kemudian melihat jawaban Anda :) Ini untuk berpikir sama! +1. Juga dengan cara ini banyak hal dapat mendengarkan hasil dari AsyncTask!
Roloc
8
Saya mendapatkan pengecualian nullpointer karena delegasi ditetapkan ke nol, mohon
klarifikasi
2
Hanya sebuah catatan untuk pengembang .net, seseorang dapat menggunakan AutoResetEvents untuk mencapai ini dan ada juga implementasi java untuk autoresetevents tetapi ini jauh lebih bersih. Omong-omong, apakah thread ProcessFinish aman?
Syler
13
untuk semua orang yang mendapatkan null pointer, lewati antarmuka Anda ke konstruktor kelas asyncTask, kemudian tetapkan ke variabel, lalu panggil processfinish () pada variabel itu. Untuk referensi, lihat asnwer yang diterima. stackoverflow.com/questions/9963691/…
Cerah
2
@Sunny Anda benar ... juga, kita harus menginisialisasi objek async untuk async.delegate = ini; untuk bekerja ..
Ninja_Coder
24

Ada beberapa opsi:

  • Tempatkan AsyncTaskkelas dalam Activitykelas Anda . Dengan asumsi Anda tidak menggunakan tugas yang sama dalam banyak kegiatan, ini adalah cara termudah. Semua kode Anda tetap sama, Anda hanya memindahkan kelas tugas yang ada menjadi kelas bersarang di dalam kelas aktivitas Anda.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
    
  • Buat konstruktor khusus untuk Anda AsyncTaskyang mengambil referensi untuk Anda Activity. Anda akan instantiate tugas dengan sesuatu seperti 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
        ...
    }
    
tenang
sumber
Dalam opsi kedua: Mengapa harus melalui rasa sakit dari konstruktor dan bidang jika kelas tidak static? Gunakan saja fieldOrMethoddari MyActivityatau MyActivity.this.fieldOrMethodjika dibayangi.
TWiStErRob
@TWiStErRob kedua mengasumsikan MyAsyncTaskadalah bukan kelas batin.
quietmint
1
Oh, maaf, private/ protecteduntuk kelas tingkat atas tidak diperbolehkan, maka saya pikir itu harus statickelas non- batin.
TWiStErRob
2
Hanya berhati-hatilah bahwa kelas dalam AsyncTask dapat menjadi sumber kebocoran memori seperti yang dijelaskan di sini garena.github.io/blog/2014/09/10/android-memory-leaks
Mark Pazon
2
Memegang referensi Aktivitas juga merupakan kebocoran memori. Pendekatan callback jauh lebih baik dari ini
OneCricketeer
19

Saya merasa pendekatan di bawah ini sangat mudah.

Saya telah mendeklarasikan antarmuka untuk panggilan balik

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

Kemudian dibuat Tugas tidak sinkron untuk menanggapi semua jenis permintaan paralel

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

}

Kemudian Memanggil tugas asinkron saat mengklik tombol di kelas Aktivitas.

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


            }
        });

    }



}

Terima kasih

Arshad
sumber
17

Anda dapat mencoba kode ini di kelas Utama Anda. Itu bekerja untuk saya, tetapi saya telah menerapkan metode dengan cara lain

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}
Nicu P
sumber
2
Bisakah Anda jelaskan mengapa ini akan membantu OP dengan masalah mereka?
John Odom
3
Itu membantu saya. Saya mencoba dengan cara lain seperti jawaban dari @HelmiB tetapi saya tidak mendapatkan hasil
Nicu P
Ok maaf atas jawaban saya. Dia perlu memanggil kelas AsyncTask, dan kemudian memasukkan parameter ke panggilan ini. AsyncTask didefinisikan oleh 3 tipe umum: 1 params (domain server atau param lainnya) 2 progres (dapat dibatalkan), 3 hasil. Semua tipe ini dapat: JSONObject, atau string, atau tipe data apa pun. Ketika Anda memiliki kelas AsyncTask, Anda harus menentukan di mana harus mengirim data. mis: asyncTask.execute (" sampletargeturl.com"). get () ;
Nicu P
Saat menggunakan metode ini, saya mendapat peringatan di Logcat: "Saya / Koreografer ﹕ Melompati 50 frame! Aplikasi mungkin melakukan terlalu banyak pekerjaan pada utas utamanya." Bagaimana cara menghadapinya? Apakah UI dibekukan saat menunggu dikembalikan dari AsyncTask?
Huy Do
@NicuP Anda mungkin lupa menelepon execute(), lihat jawaban saya, saya sudah menambahkan komentar di sana. Anda mungkin ingin memeriksa jawaban saya yang diperbarui. semoga ini membantu.
HelmiB
16

Jawaban ini mungkin terlambat tetapi saya ingin menyebutkan beberapa hal ketika Anda Activitybergantung pada AsyncTask. Itu akan membantu Anda dalam mencegah crash dan manajemen memori. Seperti yang sudah disebutkan dalam jawaban di atas interface, kami juga mengatakan mereka dipanggil kembali. Mereka akan bekerja sebagai informan, tetapi tidak pernah mengirim referensi kuatActivity atau interfaceselalu menggunakan referensi lemah dalam kasus-kasus tersebut.

Lihat screenshot di bawah ini untuk mengetahui bagaimana hal itu dapat menyebabkan masalah.

masukkan deskripsi gambar di sini

Seperti yang Anda lihat jika kami mulai AsyncTaskdengan referensi yang kuat maka tidak ada jaminan bahwa kami Activity/ Fragmentakan hidup sampai kami mendapatkan data, jadi akan lebih baik untuk digunakan WeakReferencedalam kasus-kasus itu dan itu juga akan membantu dalam manajemen memori karena kami tidak akan pernah memegang referensi yang kuat dari kami Activitymaka itu akan memenuhi syarat untuk pengumpulan sampah setelah distorsi.

Periksa cuplikan kode di bawah ini untuk mengetahui cara menggunakan WeakReference yang luar biasa -

MyTaskInformer.java Antarmuka yang akan berfungsi sebagai informan.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.javaAsyncTask untuk melakukan tugas jangka panjang, yang akan digunakan 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.javaKelas ini digunakan untuk memulai AsyncTaskimplementasiku interfacepada kelas overrideini dan metode wajib ini.

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
sumber
2
Ini bagus! poin penting yang tidak bisa diperhatikan.
HasH
6

di Oncreate Anda ():

`

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

} `

pengguna3691697
sumber
6

Anda dapat melakukannya dalam beberapa baris, cukup timpa onPostExecute saat Anda memanggil AsyncTask Anda. Ini adalah contoh untuk Anda:

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

Saya harap ini membantu Anda, selamat membuat kode :)

Ayaz Alifov
sumber
Itu tidak bekerja untuk saya. Itu tidak masuk ke onPostExecutemetode.
Francisco Romero
4

Mengapa orang membuatnya begitu sulit.

Ini harus cukup.

Jangan mengimplementasikan onPostExecute pada tugas async, melainkan menerapkannya pada Activity:

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
sumber
Ini bekerja untuk saya. Ini adalah yang sederhana dan termudah untuk dipahami. Saya pikir itu memanfaatkan apa yang dirancang untuk dilakukan Java. Terima kasih. PS: Apakah perlu menambahkan @Override?
Pak Tua
1
Tidak. @Override hanyalah anotasi. Jadi, Anda memberi tahu kompiler java bahwa Anda bermaksud mengganti metode dan mendapat informasi jika Anda tidak melakukannya.
bugdayci
4

Anda dapat memanggil get()metode AsyncTask(atau kelebihan beban get(long, TimeUnit)). Metode ini akan memblokir sampai AsyncTaskselesai pekerjaannya, pada titik mana ia akan mengembalikan Anda Result.

Adalah bijaksana untuk melakukan pekerjaan lain antara penciptaan / mulai tugas async Anda dan memanggil getmetode, jika tidak, Anda tidak memanfaatkan tugas async dengan sangat efisien.

nicholas.hauschild
sumber
1
Dikurangi vecause get () akan memblokir utas utama. Tidak ada alasan untuk menggunakan AsyncTask jika akan memblokir
GabrielBB
3

Anda dapat menulis pendengar Anda sendiri. Ini sama dengan jawaban HelmiB tetapi terlihat lebih alami:

Buat antarmuka pendengar:

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

Kemudian tulis tugas asinkron Anda:

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

Akhirnya terapkan pendengar dalam aktivitas:

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

Dan ini adalah bagaimana Anda dapat memanggil 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
sumber
2

Hai, Anda dapat membuat sesuatu seperti ini:

  1. Buat kelas yang mengimplementasikan 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. Tambahkan dalam Kegiatan Utama

    // 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
sumber
1

Buat anggota statis di kelas Aktivitas Anda. Kemudian tetapkan nilai selamaonPostExecute

Misalnya, jika hasil AsyncTask Anda adalah sebuah String, buat string statis publik di Aktivitas Anda

public static String dataFromAsyncTask;

Kemudian, di onPostExecuteAsyncTask, cukup buat panggilan statis ke kelas utama Anda dan atur nilainya.

MainActivity.dataFromAsyncTask = "result blah";

mrres1
sumber
1
apa kemungkinan kebocoran memori dalam skenario ini?
Antroid
0

Saya membuatnya bekerja dengan menggunakan threading dan penangan / pesan. Langkah-langkahnya sebagai berikut: Nyatakan Dialog kemajuan

ProgressDialog loadingdialog;

Buat fungsi untuk menutup dialog saat operasi selesai.

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

    }
    };

Kode detail Eksekusi Anda:

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

Anda perlu menggunakan "protokol" untuk mendelegasikan atau menyediakan data ke Internet AsynTask.

Delegasi dan Sumber Data

Delegasi adalah objek yang bertindak atas nama, atau berkoordinasi dengan, objek lain ketika objek itu berhadapan dengan suatu peristiwa dalam suatu program. ( Definisi Apple )

protokol adalah antarmuka yang mendefinisikan beberapa metode untuk mendelegasikan beberapa perilaku.

Ini contoh lengkapnya !!!

IgniteCoders
sumber
0

coba ini:

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

    }
}

Dan contoh penggunaan:

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
sumber
0

Mungkin sedikit berlebihan tetapi saya memberikan panggilan balik untuk kedua kode eksekusi dan hasilnya. jelas untuk keamanan utas Anda ingin berhati-hati dengan apa yang Anda akses di callback eksekusi Anda.

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

Panggilan balik:

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

Dan akhirnya pelaksanaan tugas async:

 new AsyncDbCall<>(addDeviceCallback, resultCallback).execute(device);
Secara jelas
sumber
0

Semoga Anda sudah melalui ini , jika tidak silakan baca.

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

Bergantung pada sifat data hasil, Anda harus memilih opsi terbaik yang dapat Anda pikirkan.

Ini adalah pilihan yang bagus untuk menggunakan Interface

beberapa opsi lain akan menjadi ..

  • Jika kelas AsyncTask didefinisikan di dalam kelas yang Anda ingin gunakan hasilnya. Gunakan variabel global statis atau get () , gunakan dari kelas luar ( variabel volatil jika perlu). tetapi harus menyadari kemajuan AsyncTask atau setidaknya harus memastikan bahwa ia telah menyelesaikan tugas dan hasilnya tersedia melalui metode variabel global / get (). Anda dapat menggunakan polling, onProgressUpdate (Progress ...) , sinkronisasi atau antarmuka (Yang paling cocok untuk Anda)

  • Jika Hasil tersebut kompatibel untuk menjadi entri sharedPreference atau tidak apa-apa untuk disimpan sebagai file dalam memori Anda bisa menyimpannya bahkan dari tugas latar belakang itu sendiri dan bisa menggunakan onPostExecute () metode
    untuk mendapatkan diberitahu ketika hasilnya tersedia di Ingatan.

  • Jika string cukup kecil, dan akan digunakan dengan dimulainya suatu kegiatan. adalah mungkin untuk menggunakan maksud ( putExtra () ) dalam onPostExecute () , tapi ingat bahwa konteks statis tidak aman untuk menangani.

  • Jika memungkinkan, Anda dapat memanggil metode statis dari metode onPostExecute (), dan hasilnya adalah parameter Anda

Keras
sumber