7.1: Membuat AsyncTask

Daftar Isi:

Thread adalah jalur independen eksekusi dalam program yang berjalan. Saat program Android diluncurkan, sistem Waktu Proses Android membuat thread yang bernama thread "Main". Saat program berjalan, setiap baris kode dieksekusi secara berkelanjutan, baris per baris. Thread utama ini adalah bagaimana aplikasi Anda berinteraksi dengan komponen dari Android UI Toolkit, dan mengapa thread utamanya kadang disebut "thread UI". Namun, kadang-kadang aplikasi perlu melakukan pekerjaan yang intensif sumber daya, seperti mengunduh file, kueri database, memutar media, atau menghitung analitik yang kompleks. Tipe pekerjaan intensif ini dapat memblokir thread UI jika semua kode dieksekusi secara berkelanjutan dalam satu thread. Saat aplikasi melakukan pekerjaan intensif, aplikasi tidak merespons ke pengguna atau menggambar di layar karena aplikasi menunggu pekerjaan selesai. Ini bisa menyebabkan kinerja yang buruk, yang memberikan dampak negatif kepada pengalaman pengguna. Pengguna bisa merasa frustasi dan menghapus aplikasi Android jika kinerja aplikasi tersebut lambat.

Agar pengalaman pengguna (UX) lancar dan merespons gestur pengguna dengan cepat, Android Framework menyediakan kelas helper bernama AsyncTask yang memproses kerja dari thread UI. AsyncTask adalah kelas Java abstrak yang menyediakan satu cara untuk memindahkan pemrosesan intensif ke thread yang terpisah, sehingga mengizinkan thread UI agar tetap responsif. Karena thread terpisah ini tidak disinkronisasi dengan thread yang memanggil, thread ini disebut thread asinkron. AsyncTask juga berisi callback yang mengizinkan Anda menampilkan hasil penghitungan kembali ke thread UI.

Dalam praktik ini, Anda akan mempelajari cara menambahkan tugas latar belakang ke aplikasi Android menggunakan AsyncTask.

Yang harus sudah Anda KETAHUI

Anda harus sudah bisa:

  • Membuat sebuah Aktivitas.
  • Menambahkan TextView ke layout untuk aktivitas tersebut.
  • Mendapatkan id untuk TextView dan menyetel kontennya secara terprogram.
  • Menggunakan tampilan Tombol dan fungsionalitas onClick.

Yang akan Anda PELAJARI

Dalam praktik ini Anda akan belajar:

  • Menambahkan AsyncTask ke aplikasi untuk menjalankan tugas di latar belakang, di luar thread UI.
  • Mengidentifikasi dan memahami manfaat dan kekurangan menggunakan AsyncTask untuk tugas latar belakang.

Yang akan Anda LAKUKAN

Dalam praktik ini Anda akan:

  • Membuat aplikasi sederhana yang mengeksekusi tugas latar belakang menggunakan AsyncTask.
  • Menjalankan aplikasi dan melihat apa yang terjadi saat memutar layar.

Ringkasan Aplikasi

Anda akan membangun aplikasi yang memiliki satu TextView dan satu tombol. Saat pengguna mengeklik tombol, aplikasi tertidur selama beberapa waktu, dan menampilkan pesan dalam TextView saat aplikasi aktif.

Berikut gambaran aplikasi yang telah selesai:

Pratinjau untuk aplikasi SimpleAsyncTask

Tugas 1: Menyiapkan Proyek SimpleAsyncTask

UI SimpleAsyncTask cukup mudah. UI ini berisi tombol yang meluncurkan AsyncTask, dan TextView yang menampilkan status aplikasi.

1.1 Membuat layout

  1. Buat proyek baru bernama SimpleAsyncTask menggunakan template Empty Activity (terima default untuk opsi lainnya).
  2. Ubah tampilan root RelativeLayout ke LinearLayout.
  3. Tambahkan elemen UI penting berikut ke layout untuk MainActivity:

    Tampilan Atribut Nilai
    LinearLayout android:orientation vertical
    TextView android:text

    android:id

    I am ready to start work!

    @+id/textView1

    Button android:text

    android:onClick

    Start Task

    startTask

    Catatan: Anda bisa menyetel tinggi dan lebar layout setiap tampilan ke ukuran apa pun, selama tampilan pada layar tidak tergantung pada ukuran layar (menggunakan wrap_content memastikan bahwa hal ini terjadi).
  4. Atribut onClick untuk tombol akan disorot dengan warna kuning, karena metode startTask() belum diimplementasikan di MainActivity. Letakkan kursor pada teks yang disorot, tekan Alt + Enter (Option + Enter di Mac) dan pilih Create 'startTask(View) dalam 'MainActivity' untuk membuat stub metode dalam MainActivity.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:paddingLeft="@dimen/activity_horizontal_margin"
       android:paddingRight="@dimen/activity_horizontal_margin"
       android:paddingTop="@dimen/activity_vertical_margin"
       android:paddingBottom="@dimen/activity_vertical_margin"
       android:orientation="vertical">
    
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@string/ready_to_start"
           android:id = "@+id/textView1"
           android:textSize="24sp"/>
    
       <Button
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@string/start_task"
           android:id="@+id/button"
           android:layout_marginTop="56dp"
           android:onClick="startTask" />
    </LinearLayout>
    

Tugas 2: Membuat subkelas AsyncTask

Karena AsyncTask adalah kelas abstrak, Anda perlu menjadikannya subkelas agar dapat menggunakannya. Dalam contoh ini, AsyncTask akan mengeksekusi tugas latar belakang sederhana, yaitu tertidur dengan durasi acak. Dalam aplikasi sesungguhnya, tugas latar belakang dapat melakukan semua jenis pekerjaan mulai dari membuat kueri database hingga menghubungkan ke internet, menghitung gerakan GO berikutnya agar Anda bisa mengalahkan pemenang GO saat ini.

AsyncTask memiliki metode berikut untuk melakukan pekerjaan dari thread utama:

  • onPreExecute(): Metode ini menjalankan thread UI, dan digunakan untuk menyiapkan tugas Anda (seperti menampilkan bilah kemajuan).
  • doInBackground(): Di sinilah tempat Anda mengimplementasikan kode untuk mengeksekusi pekerjaan yang akan dilakukan pada thread terpisah.
  • onProgressUpdate(): Ini akan dipanggil pada thread UI dan digunakan untuk memperbarui kemajuan dalam UI (seperti mengisi bilah kemajuan)
  • onPostExecute(): Lagi pada thread UI, ini akan digunakan untuk memperbarui hasil ke UI setelah AsyncTask telah selesai dimuat. Diagram untuk Membuat Thread AsyncTask
    Catatan: Thread latar belakang atau worker adalah thread yang bukan thread UI atau thread utama.

Saat Anda membuat AsyncTask, Anda perlu memberikan informasi tentang pekerjaan yang akan dilakukan, apakah harus atau bagaimana melaporkan kemajuannya, dan dalam bentuk apa untuk mengembalikan hasilnya.

Dalam latihan ini Anda akan menggunakan subkelas AsyncTask untuk mendefinisikan pekerjaan yang akan dijalankan dalam thread yang berbeda dengan thread UI, yang akan menghindari masalah kinerja apa pun.

Saat Anda menggunakan AsyncTask, Anda bisa mengonfigurasinya menggunakan parameter ini:

  • Params: Tipe data parameter yang dikirimkan ke tugas saat mengeksekusi doInBackground() metode pengganti.
  • Progress: Tipe data unit kemajuan yang dipublikasikan menggunakan onProgressUpdated() metode pengganti.
  • Result: Tipe data hasil yang diberikan oleh onPostExecute() metode pengganti.

Contohnya, AsyncTask dengan deklarasi kelas berikut akan menjadikan String sebagai parameter dalam doInBackground() (untuk digunakan dalam kueri, misalnya), Integer untuk onProgressUpdate() (persentase pekerjaan yang sudah selesai), dan Bitmap untuk hasil dalam onPostExecute() (hasil kueri):

public class MyAsyncTask extends AsyncTask <String, Integer, Bitmap>{}

2.1 Menjadikan AsyncTask Subkelas

Dalam implementasi AsyncTask pertama, subkelas AsyncTask akan menjadi sangat sederhana. Subkelas ini tidak memerlukan parameter kueri atau memublikasikan kemajuannya. Anda hanya perlu menggunakan metode doInBackground() and onPostExecute().

  1. Buat kelas Java baru bernama SimpleAsyncTask yang memperluas AsyncTask dan yang memerlukan tiga parameter tipe generik:
    • Kosong untuk parameternya karena AsyncTask ini tidak memerlukan masukan apa pun.
    • Kosong untuk tipe kemajuan, karena kemajuan tidak dipublikasikan.
    • String sebagai tipe hasil karena Anda akan memperbarui TextView dengan string saat AsyncTask telah menyelesaikan eksekusi.
      public class SimpleAsyncTask extends AsyncTask <Void, Void, String>{}
      
      Catatan: Deklarasi kelas akan digarisbawahi merah karena metode doInBackground() belum diimplementasikan.
      AsyncTask akan perlu memperbarui TextView setelah selesai tertidur. Lalu konstruktor perlu menyertakan TextView, agar dapat diperbarui dalam onPostExecute().
  2. Definisikan variabel anggota mTextView.
  3. Implementasikan konstruktor untuk AsyncTask yang memerlukan TextView dan menyetel mTextView ke yang diteruskan dalam TextView:
     public SimpleAsyncTask(TextView tv) {
        mTextView = tv;
     }
    

2.2 Mengimplementasikan doInBackground()

  1. Tambahkan metode doInBackground() yang diperlukan. Letakkan kursor pada deklarasi kelas yang disorot, tekan Alt + Enter (Option + Enter di Mac) dan pilih metode Implement. Pilih doInBackground() dan klik OK:
    @Override
    protected String doInBackground(Void... voids) {
       return null;
    }
    
  2. Implementasikan doInBackground() ke:

    • Buat integer acak antara 0 dan 10
    • Kalikan jumlahnya dengan 200
    • Buat thread saat ini agar tertidur. (Gunakan Thread.sleep()) dalam blok try/catch.
    • Kembalikan String "Awake at last after xx milliseconds" (xx adalah jumlah milidetik saat aplikasi tertidur)

      @Override
      protected String doInBackground(Void... voids) {
      
         // Generate a random number between 0 and 10
         Random r = new Random();
         int n = r.nextInt(11);
      
         // Make the task take long enough that we have
         // time to rotate the phone while it is running
         int s = n * 200;
      
         // Sleep for the random amount of time
         try {
             Thread.sleep(s);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
      
         // Return a String result
         return "Awake at last after sleeping for " + s + " milliseconds!";
      }
      

2.3 Mengimplementasikan onPostExecute()

Saat metode doInBackground() selesai, nilai yang dikembalikan secara otomatis diteruskan ke callback onPostExecute().

  1. Implementasikan onPostExecute() untuk mengambil argumen String (yang Anda definisikan dalam parameter ketiga AsyncTask dan yang metode doInBackground() kembalikan) dan tampilkan string tersebut dalam TextView:

    protected void onPostExecute(String result) {
       mTextView.setText(result);
    }
    
    Catatan: Anda bisa memperbarui UI dalam onPostExecute() karena dijalankan pada thread (UI) utama. Anda tidak dapat memanggil mTextView.setText() dalam doInBackground(), karena metode tersebut dieksekusi pada thread yang terpisah.

Tugas 3: Mengimplementasikan Langkah Terakhir

3.1 Implementasikan metode yang mulai dengan AsyncTask

Aplikasi Anda sekarang memiliki AsyncTask yang melakukan pekerjaan di latar belakang (atau akan melakukannya jika Anda tidak memanggil sleep() sebagai pekerjaan yang disimulasi.) Anda sekarang bisa mengimplementasikan metode yang dipanggil saat tombol Start Task diklik, untuk memicu tugas latar belakang.

  1. Dalam file MainActivity.java file, tambahkan variabel anggota untuk menyimpan TextView.
    private TextView mTextView;
    
  2. Dalam metode onCreate(), inisialisasi mTextView ke TextView dalam UI.
  3. Tambahkan kode ke metode startTask() untuk membuat instance SimpleAsyncTask, meneruskan TextView mTextView ke konstruktor.
  4. Panggil execute() pada instance SimpleAsyncTask tersebut.

    Catatan: Metode execute() adalah tempat Anda meneruskan dalam parameter (dipisahkan oleh koma) yang kemudian diteruskan ke doInBackground() oleh sistem. Karena AsyncTask tidak memiliki parameter, Anda akan mengosongkannya.
  5. Perbarui TextView untuk menampilkan teks "Napping…"

    public void startTask (View view) {
       // Put a message in the text view
       mTextView.setText("Napping... ");
    
       // Start the AsyncTask.
       // The AsyncTask has a callback that will update the text view.
       new SimpleAsyncTask(mTextView).execute();
    }
    

Kode Solusi untuk MainActivity:

package android.example.com.simpleasynctask;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

   // The TextView where we will show results
   TextView mTextView;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       //  Initialize mTextView
       mTextView = (TextView) findViewById(R.id.textView1);

   }

   public void startTask (View view) {
       // Put a message in the text view
       mTextView.setText("Napping... ");

       // Start the AsyncTask.
       // The AsyncTask has a callback that will update the text view.
       new SimpleAsyncTask(mTextView).execute();
   }
}

3.2 Mengimplementasikan onSaveInstanceState()

  1. Jalankan aplikasi dan klik tombol Start Task. Berapa lama aplikasi tertidur?
  2. Klik tombol Start Task lagi, dan saat aplikasi tertidur, putar perangkat. Jika tugas latar belakang selesai sebelum Anda bisa memutar ponsel, coba lagi. Atau, Anda bisa memperbarui kode dan membuatnya tertidur untuk jangka waktu yang lebih lama.

    Catatan: Anda akan melihat bahwa ketika perangkat diputar, TextView akan disetel ulang ke konten awalnya dan AsyncTask tidak bisa memperbarui TextView.

    Ada beberapa hal yang terjadi di sini:

    • Saat Anda memutar perangkat, sistem akan memulai ulang aplikasi, memanggil onDestroy() lalu onCreate(), yang memulai ulang siklus hidup aktivitas. Karena AsyncTasks tidak lagi terhubung ke siklus hidup aplikasi dan tidak bisa terhubung kembali ke aktivitas.
    • AsyncTasks akan terus berjalan hingga selesai di latar belakang, mengonsumsi sumber daya sistem, tetapi tidak pernah menampilkan hasil di UI, yang disetel ulang di onCreate(). AsyncTasks tidak akan pernah bisa memperbarui TextView yang diteruskan kepadanya, karena TextView tertentu juga telah dimusnahkan. Akhirnya, sistem akan kehabisan sumber daya dan akan gagal.
    • Bahkan tanpa AsyncTask, pemutaran perangkat akan menyetel ulang semua elemen UI ke status default-nya, yang bagi TextView mengimplikasikan string tertentu yang Anda setel dalam file activity_main.xml.

    Karena alasan ini, AsyncTasks tidak cocok untuk tugas yang mungkin terganggu oleh pemusnahan Aktivitas. Dalam kasus penggunaan di mana hal ini sangat penting, Anda bisa menggunakan tipe kelas berbeda bernama Loader, yang akan Anda implementasikan dalam praktik selanjutnya.

    Untuk mencegah TextView disetel ulang ke string awalnya, Anda perlu menyimpan statusnya. Anda sudah belajar cara memelihara status tampilan pada praktik sebelumnya menggunakan kelas SavedInstanceState.

    Sekarang Anda akan mengimplementasikan onSaveInstanceState() untuk mempertahankan konten TextView saat aktivitas secara spontan dimusnahkan.

    Catatan: Tidak semua penggunaan AsyncTask mewajibkan Anda untuk menangani status tampilan pada rotasi. Aplikasi ini menggunakan TextView untuk menampilkan hasil aplikasi, sehingga mempertahankan status akan berguna. Dalam kasus lainnya, seperti saat mengunggah file, Anda mungkin tidak akan memerlukan informasi persisten dalam UI, sehingga mempertahankan status tidaklah penting.
  3. Ganti metode onSaveInstanceState() dalam MainActivity untuk mempertahankan teks di dalam TextView saat aktivitas dimusnahkan:

    outState.putString(TEXT_STATE, mTextView.getText().toString());
    
  4. Ambil nilai TextView saat aktivitas dipulihkan dalam metodeonCreate().
    // Restore TextView if there is a savedInstanceState
    if(savedInstanceState!=null){
      mTextView.setText(savedInstanceState.getString(TEXT_STATE));
    }
    

Kode Solusi untuk MainActivity:

package android.example.com.simpleasynctask;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

/**
 * The SimpleAsyncTask app contains a button that launches an AsyncTask
 * which sleeps in the asynchronous thread for a random amount of time.
 */
public class MainActivity extends AppCompatActivity {

    //Key for saving the state of the TextView
    private static final String TEXT_STATE = "currentText";

    // The TextView where we will show results
    private TextView mTextView = null;

    /**
     * Initializes the activity.
     * @param savedInstanceState The current state data
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //  Initialize mTextView
        mTextView = (TextView) findViewById(R.id.textView1);

        // Restore TextView if there is a savedInstanceState
        if(savedInstanceState!=null){
           mTextView.setText(savedInstanceState.getString(TEXT_STATE));
        }
    }

    /**`
     * Handles the onCLick for the "Start Task" button. Launches the AsyncTask
     * which performs work off of the UI thread.
     *
     * @param view The view (Button) that was clicked.
     */
    public void startTask (View view) {
        // Put a message in the text view
        mTextView.setText(R.string.napping);

        // Start the AsyncTask.
        // The AsyncTask has a callback that will update the textview.
        new SimpleAsyncTask(mTextView).execute();
    }

    /**
     * Saves the contents of the TextView to restore on configuration change.
     * @param outState The bundle in which the state of the activity is saved       when it is spontaneously destroyed.
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // Save the state of the TextView
        outState.putString(TEXT_STATE, mTextView.getText().toString());
    }
}

Kode Solusi

Proyek Android Studio: SimpleAsyncTask

Tantangan penyusunan kode

Catatan: Semua tantangan penyusunan kode opsional dan bukan prasyarat untuk pelajaran berikutnya.

Tantangan: AsyncTask menyediakan metode penggantian sangat berguna lainnya: onProgressUpdate(), yang mengizinkan Anda untuk memperbarui UI saat AsyncTask berjalan. Gunakan metode ini untuk memperbarui UI dengan waktu tidur saat ini. Periksa dokumentasi AsyncTask untuk melihat bagaimana onProgressUpdate() diimplementasikan dengan tepat. Ingatlah bahwa dalam definisi kelas AsyncTask, Anda akan perlu menentukan tipe data yang akan digunakan dalam metode onProgressUpdate().

Rangkuman

  • Hindari pekerjaan intensif sumber daya dalam thread UI yang akan membuat UI Anda lamban atau tidak menentu.
    • Kode apa pun yang tidak melibatkan penggambaran UI atau merespons masukan pengguna harus dipindahkan dari thread UI ke thread berbeda yang terpisah.
  • AsyncTask adalah kelas Java abstrak yang memindahkan pemrosesan intensif ke thread yang terpisah.
    • AsyncTask harus dijadikan subkelas agar bisa digunakan.
    • AsyncTask memiliki 4 metode yang berguna: onPreExecute(), doInBackground(), onPostExecute() dan onProgressUpdate().
  • doInBackground() adalah satu-satunya metode yang dijalankan pada thread worker yang terpisah.
    • Anda tidak boleh memanggil metode UI dalam metode AsyncTask.
    • Metode AsyncTask lainnya berjalan dalam thread UI dan mengizinkan metode memanggil komponen UI.
  • Memutar perangkat Android akan memusnahkan dan membuat ulang aktivitas Hal ini bisa memutuskan UI dari thread latar belakang, yang akan terus berjalan.

Konsep terkait

Dokumentasi konsep terkait ada di Dasar-Dasar Developer Android: Konsep.

Ketahui selengkapnya

Dokumentasi Developer Android

Sumber daya lainnya

Video

results matching ""

    No results matching ""