Berjalan di
Latar
Belakang
Apa yang akan kita bahas:
• UI thread
Konsep Dasar
Saat Anda meluncurkan aplikasi, sebuah proses dibuat, dan itu mengalokasikan
beberapa sumber daya seperti memori, antara lain. Itu juga diberikan satu utas.
Sebuah utas, secara longgar, adalah urutan instruksi. Itu adalah hal yang mengeksekusi
kode Anda. Selama aplikasi hidup, utas ini akan menggunakan sumber daya proses. Mungkin
membaca atau menulis data ke memori, disk, atau kadang-kadang bahkan jaringan I/O.
Sementara utas berinteraksi dengan semua ini, itu hanya menunggu. Itu tidak dapat
memanfaatkan siklus CPU saat menunggu. Kami tidak bisa membiarkan semua siklus CPU
itu sia-sia. Bisakah kita? Kita dapat membuat utas lain sehingga ketika satu atau lebih utas
menunggu sesuatu, utas lainnya dapat menggunakan CPU. Ini adalah kasus untuk aplikasi
multithreaded.
131
© Ted Hagos 2020
T. Hagos, Pelajari Android Studio 4,
https://doi.org/10.1007/978-1-4842-5937-
5_11
Saat Android Runtime membuat instance aplikasi, proses itu akan diberikan satu
benang. Ini disebut utas utama; beberapa pengembang menyebutnya utas UI, tetapi kami
hanya akan diberikan satu utas dan tidak lebih. Kabar baiknya adalah kita dapat membuat
lebih banyak utas. Utas UI diizinkan untuk menelurkan utas lainnya.
Utas UI Utas
UI, juga dikenal sebagai utas utama, bertanggung jawab untuk meluncurkan aktivitas
utama dan mengembangkan file tata letak (XML). Menggembungkan file layout berarti
mengubah semua elemen View menjadi objek Java yang sebenarnya, misalnya Buttons,
TextViews, dan sebagainya. Singkatnya, utas utama bertanggung jawab untuk
menampilkan UI. Saat kita membuat panggilan
seperti setText() atau setHint() pada objek TextView, panggilan ini tidak langsung
dieksekusi; sebagai gantinya, itu adalah sebagai berikut:
1. Panggilan ditempatkan di MessageQueue.
Utas utama tidak hanya digunakan untuk menampilkan elemen UI, tetapi
juga digunakan untuk semua hal lain yang terjadi di aplikasi Anda. Anda
mungkin ingat bahwa Aktivitas memiliki metode siklus hidup seperti onCreate,
onStop, onResume, onCreateOptionsMenu,
onOptionsItemSelected, dan metode lainnya. Setiap kali kode berjalan pada blok ini, runtime
tidak dapat memproses pesan apa pun dalam antrian. Itu dalam diblokir ; keadaan diblokir
berarti bahwa utas utama sedang menunggu sesuatu untuk diselesaikan sebelum dapat
melanjutkan bisnisnya—ini tidak baik untuk pengalaman pengguna.
Sebagian besar waktu, panggilan yang kita buat tidak memakan banyak waktu untuk
dijalankan. Panggilannya murah, bisa dikatakan, dalam hal sumber daya komputasi. Jadi,
sebenarnya bukan masalah besar. Ini
menjadi masalah besar ketika kami melakukan panggilan yang membutuhkan waktu cukup
lama untuk diselesaikan. Panduan tim pengembangan Android adalah bahwa kita harus
membatasi panggilan kita tidak lebih dari 15 milidetik; lebih dari itu, maka kita harus
mempertimbangkan untuk menjalankan kode-kode itu
di utas latar belakang. Panduan ini berasal dari Project Butter, yang dirilis sekitar waktu
Jelly Bean (Android 4.1); itu dimaksudkan untuk meningkatkan kinerja aplikasi Android.
Ketika runtime merasakan bahwa Anda melakukan terlalu banyak pada utas utama, itu akan
mulai menjatuhkan bingkai. Saat Anda tidak melakukan panggilan yang mahal, aplikasi
berjalan pada 60 frame per detik yang sangat mulus. Jika Anda memonopoli utas utama,
Anda akan mulai melihat
kinerja yang lamban karena kecepatan bingkai mulai turun. Di dunia Android, ini dikenal
sebagai jank. Melakukan terlalu banyak pemrosesan pada utas utama akan menyebabkan
rendering UI yang lambat, yang mengakibatkan bingkai jatuh atau dilewati, yang
mengakibatkan aplikasi dianggap gagap. Aplikasi menjadi tersendat.
Jika Anda ingin menghindari jank, Anda perlu tahu cara menjalankan kode yang
memakan waktu atau terkait I/O di latar belakang.
Anda tidak perlu terlalu bersemangat dan mulai menjalankan semuanya di latar
belakang. Bersikaplah masuk akal dan gunakan penilaian Anda. Panggilan berikut,
misalnya, tidak perlu berada di utas latar belakang:
txt1.setText(String.format("%d", (2 * 2 * 2)));
Ini hanya mengatur properti Text dari TextView ke bidang terhitung. Perhitungannya
tidak rumit.
Bahkan Listing 11-1 tidak dianggap sebagai kode yang mahal untuk dijalankan. Itu
melakukan beberapa perhitungan dasar dari GCF (faktor persekutuan terbesar), tetapi
menggunakan algoritma Euclidean untuk mendapatkan hasilnya. Algoritma ini bekerja
secara efisien. Jumlah
siklus loop tidak bertambah besar terlepas dari seberapa besar nilai inputnya;
kompleksitas waktu tidak banyak berubah apakah kita menemukan GCF dari 12 dan 15
atau 16.848.662 dan 24. Jadi, cukup baik untuk menempatkan ini di utas utama.
}
String pesan = String.format("GCF = %s", smallno);
Toast.makeText(ini, msg, Toast.LENGTH_LONG).show();
}
Listing 11-2, di sisi lain, adalah panggilan yang mahal. Tampaknya dibuat-buat sekarang,
tetapi
Anda akan terkejut menemukan bahwa jenis kode ini benar-benar ada dan mungkin lebih
umum daripada yang Anda pikirkan—ketika Anda cukup sering duduk untuk meninjau kode,
Anda akan tahu apa yang saya maksud. Bagaimanapun, Anda harus berhati-hati terhadap
kode seperti ini karena, meskipun tidak memiliki jaringan atau panggilan I/O, kode tersebut
menggunakan benang UI untuk menghitung produk Cartesian—kumpulan matematika
produk Cartesian yang merupakan hasil perkalian dengan yang lain. set. Kode yang
terstruktur serupa paling baik ditempatkan di utas latar belakang.
Contoh kode lain yang perlu dijalankan di latar belakang adalah Listing 11-3. Ini
menggunakan Internet untuk mengambil informasi dari GitHub.
.url(url)
.build();
• AsyncTaskframework Android
Teknik apa pun yang Anda gunakan, prinsipnya akan tetap sama; dan itu adalah
}
}
Kelas Worker hanya memperluas java.lang.Thread. Anda perlu mengganti metode run()
dari utas dan meletakkan semua pernyataan yang ingin Anda jalankan di latar belakang
di dalamnya. Setelah itu, yang tersisa untuk dilakukan adalah membuat instance
Worker dan menjalankannya, seperti yang ditunjukkan pada Listing 11-5.
(); Buat
}
}
Seperti yang Anda lihat, itu tidak jauh berbeda dari sampel kami sebelumnya; alih-alih
memperluas
Thread, kami hanya mengimplementasikan antarmuka Runnable. Anda masih perlu
mengganti metode run() dan meletakkan pernyataan yang ingin Anda jalankan di latar
belakang dalam metode run() . Perbedaannya tidak terletak pada struktur kelas Worker,
tetapi bagaimana kelas Worker dipakai dan dijalankan, yang ditunjukkan pada Listing 11-7.
Worker.
Buat instance kelas thread dengan meneruskan instance kelas runnable (instance
Worker) ke konstruktor thread.
sekarang kita dapat memulai thread dengan memanggil metode start() .
Sekarang kita memiliki ide konseptual tentang cara menggunakan Utas, mari kita gunakan
untuk mengambil informasi pengguna dari GitHub. Daftar 11-8 menunjukkan langkah-langkah
tentang cara memanggil GitHub API menggunakan OkHttpClient.
= response.body().string(); ioe
}
) { Log.e(TAG,
ioe.getMessage());
}
kembalikan info pengguna;
}
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Tombol
android:id="@+id
/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="21dp"
android:layout_marginBottom="46dp"
android:text="Button"
app:layout_constraintBottom_toTopOf="
@+id/scrollView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android :ems="10"
android:inputType="textPersonName"
aplikasi:layout_constraintStart_toStartOf="@+id/bu
tton"
aplikasi:layout_constraintTop_toBottomOf="@+id/button" />
<ScrollView
android:id="@+id/scrollView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
aplikasi:layout_const aplikasi
raintBottom_toBottomOf="induk":layout_constraintEn
d_toEndOf="induk"
aplikasi:layout_constraintStart_toStartOf="induk"
aplikasi:layout_constraintTop_toBottomOf="@+id/but
ton">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent_w
idth "
android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:typeface="monospace" />
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Selanjutnya, mari kita urus file manifesnya. Kita perlu mengakses Internet saat kita
memanggil GitHub API; jadi, mari kita nyatakan itu di AndroidManifest . Masukkan izin
penggunaan INTERNET dalam manifes, seperti yang ditunjukkan pada Daftar 11-10.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.workingdev.ch11_threads">
<menggunakan -permission android:name="android.permission.INTERNET" />
<application>
...
</application>
</manifest>
Selanjutnya, mari kita berurusan dengan file Gradle. Ada dua perubahan yang perlu kita
buat pada file Gradle modul aplikasi. Pertama, kita perlu menambahkan entri
ketergantungan untuk OkHttpClient. Kedua, kita perlu menambahkan entri untuk
mengaktifkan View binding.
Kita tidak harus menggunakan View binding untuk contoh ini, tapi menurut saya ini
adalah cara yang baik untuk memperkenalkan fitur baru yang dapat membuat pemrograman
kita lebih mudah. View binding memungkinkan kita menulis kode yang berinteraksi dengan
Views. Setelah View binding diaktifkan dalam modul, itu menghasilkan kelas binding untuk
setiap file tata letak XML yang ada dalam modul itu. Instance dari kelas binding berisi
referensi langsung ke semua tampilan dengan ID dalam
tata letak yang sesuai. Dalam kebanyakan kasus, View binding menggantikan
findViewByID. Edit file Gradle modul dan modifikasi agar sesuai dengan Listing 11-11.
Daftar 11-11. build.gradle (Modul: aplikasi)
menerapkan plugin:
'com.android.application' android {
buildFeatures { viewBinding
= true
compileSdkVersion 29
defaultConfig {
...
buildTypes {
rilis {
...
}
}
}
dependensi {
masukkan
blok ini untuk mengaktifkan View binding. Menyetel viewBinding ke true
memungkinkan View binding untuk modul ini.
. masukkan ketergantungan ini sehingga kita dapat menggunakan okhttpClient
= binding.textView; binding.button.setOnClickListener
(New View.OnClickListener() { @Override
String
public void onClick(View view) {
Log.d(TAG, "Click");
username = binding.txtName.getText().toString() ; RunBackground
(); .start
}
});
}
textView sebagai anggota karena kita akan menggunakannya nanti, di luar metode
onCreate()
.
metode inflate Panggil () (secara statis) untuk membuat instance kelas
binding untuk digunakan Mainactivity.
getRoot dapatkan referensi tampilan root dengan memanggil ().
alih -alih meneruskan nama file tata letak (activity_main), alih-alih meneruskan tampilan
root.
; Mari kita mendapatkan referensi ke objek textViewdisini kita akan
mengirimkan hasil dari github api call.
Mari kita siapkan pendengar klik untuk Tombol.
. dapatkan konten teks edit
buat instance objek utas dan mulai. Kami belum mendefinisikan objek utas; kami
akan melakukannya segera. Daftar 11-13 menunjukkan RunBackground
diimplementasikan sebagai kelas dalam di Mainactivity.
Daftar 11-13. RunBackground kelas dalam kelas
publik MainActivity memperluas AppCompatActivity {
catch(JSONException e) {
Log.e(TAG, e.getMessage());
}
}
}
private String fetchUserInfo(String gitHubId) {
}
Mari
... kita perluas kelas thread karena kita ingin ini berjalan di
latar belakang. Kami menerapkan ini juga sebagai kelas
dalam untuk memiliki akses ke anggota kelas luar
(Mainactivity).
Mari kita ambil nama pengguna github sebagai parameter untuk
konstruktor kelas ini.
menimpa metode run() . segala sesuatu di dalam metode ini adalah
apa yang akan berjalan di latar belakang.
fetchUserInfoMari kita panggil metode () .
githubapi akan mengembalikan hasilnya sebagai String. jika
Anda perlu bekerja dengan objek yang dikembalikan
sebagai Json, Anda perlu menggunakan JSONObject,
seperti yang ditunjukkan di sini. dengan cara ini, jika Anda
ingin mengekstrak
bagian tertentu dari info pengguna, Anda dapat membuat
Ringkasan
• Saat Anda mencoba melakukan terlalu banyak
pada utas utama, waktu proses mungkin mulai
menurunkan kecepatan bingkai, yang
mengakibatkan jank.
• Utas UI bertanggung jawab untuk membuat elemen
UI, antara lain. Jangan membebani thread ini. Jika
Anda perlu melakukan beberapa tugas yang
memakan waktu atau sumber daya, buat utas latar
belakang dan lakukan tugas itu di sana.