Pertanyaan AsyncTask doInBackground tidak menjalankan [duplikat]


Pertanyaan ini sudah memiliki jawaban di sini:

Saya mengalami masalah dengan kelas AsyncTask. Sepertinya tugas saya berhenti berfungsi setelah membuat 4 atau 5 tugas.

Saya memiliki 2 kegiatan. MainActivity yang hanya memegang tombol yang memulai aktivitas kedua yang disebut ImageActivity.

ImageActivity sangat sederhana. itu mendapat onCreate yang mengatur tata letak, dan kemudian memulai AsyncTask baru yang memuat gambar dari internet. Ini berfungsi dengan baik beberapa kali pertama. Tetapi dari itu tiba-tiba berhenti bekerja. Metode onPreExecute dijalankan setiap waktu, tetapi bukan metode doInBackground. Saya telah mencoba menyederhanakan doInBackground dengan loop tidur, dan hal yang sama terjadi. Saya tidak dapat memahami perilaku ini karena asynctask dibatalkan dan disetel ke null dalam metode onDestroy. Jadi setiap kali saya memulai ImageActivity baru, saya juga membuat AsyncTask yang baru.

Saya menciptakan kembali ImageActivity dan tugas dengan menekan tombol kembali, dan daripada mengklik tombol pada MainActivity.

Ada ide siapa saja? Saya benar-benar berjuang dengan yang satu ini.

UPDATE: Kode yang memulai ImageActivity (di dalam tombol onClickListener)

Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setClassName(this, ImageActivity.class.getName());
startActivity(intent);

Kode di atas memulai aktivitas ini

    public class ImageActivity extends Activity {

    private AsyncTask<Void, Void, Void> task;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        task = new AsyncTask<Void, Void, Void>() {

            @Override
            protected void onPreExecute()
            {
                Log.d(TAG, "onPreExecute()");
            }

            @Override
            protected Void doInBackground(Void... params)
            {
                Log.d(TAG, "doInBackground() -- Here is the download");
                // downloadBitmap("http://mydomain.com/image.jpg")
                return null;
            }

            @Override
            protected void onPostExecute(Void res)
            {
                Log.d(TAG, "onPostExecute()");
                if(isCancelled()){
                    return;
                }
            }
        }.execute();
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        task.cancel(true);
    }
}

MEMPERBARUI:

Saya telah menguji menggunakan kombinasi Thread tradisional dan metode runOnUiThread, dan tampaknya bekerja lebih baik. Sekarang utasnya berjalan setiap waktu.


32
2017-11-02 18:17


asal


Jawaban:


Menghapus AsyncTask dan menggunakan Benang tradisional bukannya menggabungkannya dengan runOnUiThread sepertinya berhasil. Tapi saya masih belum menemukan alasan mengapa AsyncTask sangat "tidak stabil".

Ini kode yang cocok untuk saya:

public class ImageActivity extends Activity {

    private Thread worker;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        worker = new Thread(new Runnable(){

            private void updateUI(final List<Object> list)
            {
                if(worker.isInterrupted()){
                    return;
                }
                runOnUiThread(new Runnable(){

                    @Override
                    public void run()
                    {
                        // Update view and remove loading spinner etc...
                    }
                });
            }

            private List<Object> download()
            {
                // Simulate download
                SystemClock.sleep(1000);
                return new ArrayList<Object>();
            }

            @Override
            public void run()
            {
                Log.d(TAG, "Thread run()");
                updateUI(download());
            }

        });
        worker.start(); }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        worker.interrupt();
    }
}

22
2017-11-03 08:11



Saya mengalami masalah serupa. Anda tidak dapat menjalankan beberapa Asynctasks secara paralel hingga SDK 11. Periksa di sini untuk info lebih lanjut


7
2018-02-03 07:29



Saya baru saja mengalami masalah ini juga. Jika Anda menggunakan AsyncTask.execute, tugas Anda dijalankan pada antrean serial (dari sumber Android 4.3):

Ketika pertama kali diperkenalkan, AsyncTasks dieksekusi secara serial pada single   utas latar belakang. Dimulai dengan DONUT, ini diubah menjadi kumpulan   utas memungkinkan banyak tugas untuk beroperasi secara paralel. Dimulai dengan   HONEYCOMB, tugas dijalankan pada satu utas untuk menghindari umum   kesalahan aplikasi yang disebabkan oleh eksekusi paralel.

Ini konsisten dengan perilaku yang saya lihat. Saya punya AsyncTask muncul dialog di doInBackground dan diblok sampai dialog ditutup. Dialog itu membutuhkan miliknya sendiri AsyncTask untuk menyelesaikan. Dialognya AsyncTask.doInBackground metode tidak pernah dieksekusi karena aslinya AsyncTask masih diblokir.

Solusinya adalah mengeksekusi yang kedua AsyncTask secara terpisah Executor.


5
2017-12-16 20:49



Gunakan traceview untuk menyelidiki - atau dapatkan thread dump. Tebakan saya adalah bahwa salah satu utas AsyncTask Anda tergantung pada unduhan.

AsyncTask memiliki kolam thread kecil, jadi jika salah satu tugas Anda hang, itu bisa berakhir dengan memblokir kumpulan thread Anda.

Berikut adalah tes cepat yang dapat Anda jalankan - pada 4.3, saya melihat bahwa saya hanya memiliki 5 rangkaian konkuren yang dapat saya jalankan. Saat satu utas keluar, utas lainnya mulai.

  private void testAsyncTasks() {

        for (int i = 1; i <= 10; i++) {
              final int tid = i;
              new AsyncTask<Integer, Void, Void>() {
                    protected void onPreExecute() {
                          Log.d("ASYNCTASK", "Pre execute for task : " + tid);
                    };

                    @Override
                    protected Void doInBackground(Integer... args) {
                          int taskid = args[0];
                          long started = SystemClock.elapsedRealtime();
                          Log.d("ASYNCTASK", "Executing task: " + taskid + " at " + started);
                          for (int j = 1; j <= 20; j++) {
                                Log.d("ASYNCTASK", "   task " + taskid + ", time=" + (SystemClock.elapsedRealtime() - started));
                                SystemClock.sleep(1000);
                          }
                          return null;
                    }

                    protected void onPostExecute(Void result) {
                          Log.d("ASYNCTASK", "Post execute for task : " + tid);
                    };
              }.execute(i);

        }
  }

1
2017-09-21 13:20



Anda tidak perlu khawatir tentang benang rumah tangga di Android karena dikelola oleh sistem.

Silakan juga posting metode pengunduhan gambar. Apakah Anda juga mencoba untuk tidak membatalkan thread dalam metode onDestroy ()? Bagaimana Anda mengembalikan gambar ke utas UI Anda?


0
2017-11-02 19:37



Masalah yang saya percaya adalah dengan tugas unduh gambar yang berat. Bahkan jika Anda membatalkan tugas async, unduhan gambar akan terus dijalankan dan tugas async tidak selesai sampai pengunduhan selesai. Anda mungkin ingin memeriksa metode isCancelled () di AyncTask ketika unduhan sedang berlangsung dan mematikan unduhan jika tugas dibatalkan.

Untuk referensi, inilah dokumentasi tentang metode cancel (): Berusaha membatalkan pelaksanaan tugas ini. Upaya ini akan gagal jika tugas telah selesai, sudah dibatalkan, atau tidak dapat dibatalkan karena beberapa alasan lain. Jika berhasil, dan tugas ini belum dimulai saat membatalkan dipanggil, tugas ini tidak boleh berjalan. Jika tugas telah dimulai, maka parameter mayInterruptIfRunning menentukan apakah thread yang mengeksekusi tugas ini harus diinterupsi dalam upaya untuk menghentikan tugas. Memanggil metode ini akan menghasilkan onCancelled (Object) yang dipanggil pada untaian UI setelah mengembalikan is_Background (Object []). Memanggil metode ini menjamin bahwa onPostExecute (Objek) tidak pernah dipanggil. Setelah menerapkan metode ini, Anda harus memeriksa nilai yang dikembalikan oleh isCancelled () secara berkala dari doInBackground (Objek []) untuk menyelesaikan tugas sedini mungkin.


0
2018-04-13 11:44



Saya punya ini juga, tidak ada alasan nyata untuk tidak memulai. Saya telah memperhatikan bahwa setelah merestart adb, itu berhasil lagi. Tidak yakin mengapa ini, tetapi itu berhasil bagi saya


0
2018-03-02 10:21