7.1: Membuat AsyncTask
Daftar Isi:
- Yang harus sudah Anda KETAHUI
- Yang akan Anda PELAJARI
- Yang akan Anda LAKUKAN
- Tugas 1: Menyiapkan proyek SimpleAsyncTask
- Tugas 2: Membuat subkelas AsyncTask
- Tugas 3: Mengimplementasikan Langkah Terakhir
- Tantangan penyusunan kode
- Rangkuman
- Konsep terkait
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:
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
- Buat proyek baru bernama SimpleAsyncTask menggunakan template Empty Activity (terima default untuk opsi lainnya).
- Ubah tampilan root
RelativeLayout
keLinearLayout
. 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 (menggunakanwrap_content
memastikan bahwa hal ini terjadi).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.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()
.
- 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 metodeAsyncTask akan perlu memperbarui TextView setelah selesai tertidur. Lalu konstruktor perlu menyertakan TextView, agar dapat diperbarui dalamdoInBackground()
belum diimplementasikan.onPostExecute()
.
- Definisikan variabel anggota mTextView.
- 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()
- Tambahkan metode
doInBackground()
yang diperlukan. Letakkan kursor pada deklarasi kelas yang disorot, tekan Alt + Enter (Option + Enter di Mac) dan pilih metode Implement. PilihdoInBackground()
dan klik OK:@Override protected String doInBackground(Void... voids) { return null; }
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()
.
Implementasikan
onPostExecute()
untuk mengambil argumenString
(yang Anda definisikan dalam parameter ketiga AsyncTask dan yang metodedoInBackground()
kembalikan) dan tampilkan string tersebut dalam TextView:protected void onPostExecute(String result) { mTextView.setText(result); }
Catatan: Anda bisa memperbarui UI dalamonPostExecute()
karena dijalankan pada thread (UI) utama. Anda tidak dapat memanggilmTextView.setText()
dalamdoInBackground()
, 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.
- Dalam file MainActivity.java file, tambahkan variabel anggota untuk menyimpan TextView.
private TextView mTextView;
- Dalam metode
onCreate()
, inisialisasimTextView
ke TextView dalam UI. - Tambahkan kode ke metode
startTask()
untuk membuat instanceSimpleAsyncTask
, meneruskan TextViewmTextView
ke konstruktor. Panggil
execute()
pada instanceSimpleAsyncTask
tersebut.Catatan: Metodeexecute()
adalah tempat Anda meneruskan dalam parameter (dipisahkan oleh koma) yang kemudian diteruskan kedoInBackground()
oleh sistem. Karena AsyncTask tidak memiliki parameter, Anda akan mengosongkannya.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()
- Jalankan aplikasi dan klik tombol Start Task. Berapa lama aplikasi tertidur?
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()
laluonCreate()
, 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.- Saat Anda memutar perangkat, sistem akan memulai ulang aplikasi, memanggil
Ganti metode
onSaveInstanceState()
dalam MainActivity untuk mempertahankan teks di dalam TextView saat aktivitas dimusnahkan:outState.putString(TEXT_STATE, mTextView.getText().toString());
- Ambil nilai TextView saat aktivitas dipulihkan dalam metode
onCreate()
.// 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
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()
danonProgressUpdate()
.
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
- Proses dan thread
- Memproses Bitmaps di luar thread UI menggunakan AsyncTask
- AsyncTask
Sumber daya lainnya
Video
- Dasar-Dasar Kinerja Threading oleh Performance Guru Colt McAnlis. Pelajari lebih lanjut tentang thread utama dan mengapa menjalankan tugas yang berjalan lama di thread utama sangat buruk.
- Hunting AsyncTask yang Baik oleh Colt McAnlis. Ketahui selengkapnya tentang AsyncTasks