Anda di halaman 1dari 25

BAB 11

Berjalan di
Latar
Belakang
Apa yang akan kita bahas:

• Konsep thread dasar

• UI thread

• Cara membuat dan menggunakan thread Java

Mengetahui cara menjalankan kode di latar belakang merupakan keterampilan penting


bagi setiap pengembang. Memanfaatkan utas dengan mahir dapat meningkatkan kinerja
aplikasi Anda. Pengguna menyukainya. Bilah sangat tinggi sekarang pada kinerja aplikasi.
Tidak ada yang ingin menggunakan aplikasi yang berjalan seperti tetes tebu. Aplikasi gelisah
dan tersendat dengan cepat dilupakan saat ini.
Dalam bab ini, kita akan menjelajahi dunia Thread yang indah.

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.

2. Di sana ia akan tetap ada sampai pawang mengambilnya untuk dieksekusi.

3. Kemudian, itu akan dieksekusi di utas utama.

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.

Catatan Sebelum memproyeksikan Butter, jika utas ui


merasakan bahwa Anda melakukan terlalu banyak pada utas ui,
misalnya, membuka file besar, membuat soket jaringan, atau apa
pun yang membutuhkan waktu lama, runtime mungkin menampar
Anda layar anr (android tidak merespons). anrs jarang terlihat saat
ini; jank lebih menjadi perhatian.

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.

Daftar 11-1. Perhitungan GCF


private void gcfCalculate(int firstNo, int secondNo) {
int rem, bigno, smallno = 1;
if (firstNo > secondNo) { bigno = firstNo; smallno = secondNo;}
else {bigno = secondNo; smallno = firstNo;}
while(!((rem = bigno % smallno) == 0)) {
bigno = smallno;
kecil = rem;

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

Daftar 11-2. Panggilan bersarang


private void nestedCall()
{ for(int i = 1; i < 10000; i++)
{
for(int j = 1; j < 10000; j++)
{ for(int k = 1; k < 10000; k++)
{ Sistem.keluar.printf("%d", i * j *
k);
}
}
}
}

Contoh kode lain yang perlu dijalankan di latar belakang adalah Listing 11-3. Ini
menggunakan Internet untuk mengambil informasi dari GitHub.

Daftar 11-3. Dapatkan info GitHub


private String fetch(String gitHubId)
{ String userInfo = "";
String url = String.format("https://api.github.com/users/%s", gitHubId);
Klien OkHttpClient = baru ();
Permintaan permintaan = new Request.Builder()

.url(url)
.build();

coba(Respon respon = client.newCall(request).execute())


{ userInfo = response.body().string();
}
tangkap(IOException ioe)
{ Log.e(TAG,
ioe.getMessage());
}
kembalikan info pengguna;
}

Android Runtime akan memukul Anda dengan NetworkonMainThreadException jika


Anda mencoba menjalankan ini di thread UI. Kode apa pun yang menggunakan konektivitas
jaringan tidak dapat berjalan di utas UI.
Saat Anda berada dalam situasi di mana Anda perlu (1) mengambil atau menulis data
menggunakan jaringan, (2) mengambil atau menulis data menggunakan file I/O, atau (3)
melakukan operasi intensif sumber daya (seperti di Listing 11-2), Anda perlu menjalankan
kode itu di utas latar belakang. Ada beberapa cara untuk melakukannya; lihat daftarnya
sebagai berikut:
• Java threads, yang berasal dari Java

• AsyncTaskframework Android

• Handler dan Messages, yang juga merupakan bagian dari


framework Android

Teknik apa pun yang Anda gunakan, prinsipnya akan tetap sama; dan itu adalah

1. Memunculkan utas latar belakang saat menjalankan tugas yang


sudah berjalan lama atau memakan sumber daya.
2. Jika Anda perlu melakukan sesuatu di utas UI (seperti menyetel
properti Tampilan) saat berada di dalam utas latar belakang, Anda
harus menemukan cara untuk kembali ke utas UI sebelum
mengerjakan elemen Tampilan.
Dari semua cara untuk menjalankan kode di latar belakang, Thread akan menjadi yang
paling akrab dengan programmer Java, tetapi juga akan menjadi yang paling dasar.
Threads dan Runnables
Kita bisa menjalankan statement di background dengan memunculkan thread baru. Objek
utas dibuat dengan memperluas java.lang.Thread atau dengan mengimplementasikan
antarmuka Runnable. Objek utas menjelaskan satu utas eksekusi, dan eksekusi itu terjadi di
dalam run() .
Memperluas kelas Thread adalah cara paling sederhana untuk membuat objek thread.
Listing 11-4 menunjukkan struktur tipikal kelas Thread.

Daftar 11-4. class Worker


class Worker extends Thread {
public void run() {
// hal-hal yang ingin Anda jalankan di
// background

}
}

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.

Daftar 11-5. Cara membuat dan menjalankan thread


Worker worker = new Worker(); pekerja.start

(); Buat

instance dari kelas thread.


memanggil metode start() . jika Anda lupa ini, utasnya tidak akan berjalan.
Memanggil metode start() akan memulai utas.

Cara lain untuk membuat utas adalah dengan mengimplementasikan antarmuka


Runnable, seperti yang ditunjukkan pada Listing 11-6.
Daftar 11-6. Kelas Worker mengimplementasikan kelas antarmuka Runnable
Worker mengimplementasikan
Runnable { @Override
public void run() {
// hal-hal yang ingin Anda jalankan di
// background

}
}

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.

Daftar 11-7. Cara menggunakan objek Runnable


Worker worker = new Worker(); Utas
utas = Utas baru (pekerja);
thread.start (); instance

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.

Daftar 11-8. fetchUserInfo


private String fetchUserInfo(String gitHubId) { userInfo
= "";

String url = String.format("https://api.github.com/users/%s", gitHubId);


Log.d
(TAG, String.format("URL: %s", url));
Klien OkHttpClient = OkHttpClient baru(); .build

Permintaan permintaan = new Request.Builder()


.url(url)
();

try(Respons respons = client.newCall(request).execute()) { userInfo

= response.body().string(); ioe

}
) { Log.e(TAG,
ioe.getMessage());
}
kembalikan info pengguna;
}

useridKami ingin mengambil github sebagai parameter.


urL yang menggabungkan userid github.
OkHttpClient Kami akan menggunakan dari Square, inc. okhttpClient adalah
proyek sumber terbuka yang dirancang untuk menjadi klien http yang efisien.
ini mendukung protokol SpdY. SpdY adalah dasar untuk http 2.0 dan
memungkinkan beberapa permintaan http untuk dimultipleks melalui satu
koneksi soket; Anda dapat
mempelajari lebih lanjut tentang SpdY di https://en.wikipedia.org/wiki/SPDY.
pada android 5.0,
okhttpClient adalah bagian dari platform android dan digunakan untuk
semua panggilan http. contoh ini diambil dari halaman web okhttpClient di
https://square.github.io/okhttp/.
Mari kita gunakan coba dengan sumber daya , jadi kita tidak perlu khawatir
tentang pembersihan nanti; ketika blok coba keluar dari ruang lingkup,
semua sumber daya yang kami buka di dalam blok itu akan ditutup secara
otomatis.
jika semua pengaturan kami sebelumnya berjalan dengan baik, kami bisa mendapatkan
respons dari github api.
Kami ingin menjalankan metode fetchUserInfo() di utas latar belakang untuk
mendapatkan NetworkonMainThreadException . Mari kita buat proyek demo
kecil untuk ini. Buat proyek dengan Aktivitas kosong. Mari kita buat UI sederhana
dengan elemen berikut:

• EditText—Di mana kita bisa memasukkan userid GitHub.

• Tombol—Yang akan memicu tindakan pengguna.


• TextView—Di mana kami akan menampilkan hasil panggilan
pengambilan kami dari GitHub.

• ScrollView—Kami akan membungkus TextView di sini, sehingga


teks yang ditampilkan multiline, dan dapat digulir.

Gambar 11-1 menunjukkan tata letak aplikasi.

Gambar 11-1. Tata letak aplikasi

Buka activity_main.xml untuk mengedit dan memodifikasinya agar sesuai dengan


Listing 11-9.
Daftar 11-9. aktivitas_main.xml
<?xml version="1.0" encoding="utf-8"?>

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

Daftar 11-10. AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>

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

implementasi 'com .squareup.okhttp3:okhttp:4.7.2' ...


}

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

Anda perlu menyinkronkan file Gradle setelah mengeditnya.


Sejak Android Studio 3.6, Anda sudah dapat mengganti findViewById dengan View
binding; ketika diaktifkan untuk modul, itu menghasilkan kelas pengikatan untuk setiap file
tata letak XML yang berisi modul. Setiap kelas pengikatan berisi referensi ke tampilan root
dan semua tampilan yang memiliki ID. Nama kelas pengikatan dihasilkan dengan
mengonversi nama file XML menjadi camel case dan menambahkan kata "Binding" di akhir
—misalnya, dalam proyek kami, kami hanya memiliki activity_main.xml; jadi, kelas yang
disebut ActivityMainBinding akan dibuat untuk kita.
Listing 11-12 menunjukkan penggunaan beranotasi View binding di kelas MainActivity.

Daftar 11-12. MainActivity


mengimpor
androidx.appcompat.app.AppCompatActivity; impor
okhttp3.OkHttpClient;
impor okhttp3.Permintaan;
impor okhttp3.Response;
impor android.os.Bundle;
impor android.util.Log;
impor android.view.View;
impor android.widget.TextView;
impor net.workingdev.ch11_threads.databinding.ActivityMainBinding;
impor org.json.JSONException;
impor org.json.JSONObject;
impor java.io.IOException;
MainActivity kelas publik memperluas AppCompatActivity {
private final String TAG = getClass().getName();
TextView txtUserInfo pribadi; @Override
saveInstanceState
) { super.onCreate(savedInstanceState);
akhir ActivityMainBinding mengikat =
ActivityMainBinding. mengembang(getLayoutInflater());
binding.getRoot
(); setContentView
(tampilan); txtUserInfo

= 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 {

private final String TAG = getClass().getName();


TextView txtUserInfo pribadi;
@Override

protected void onCreate(Bundle saveInstanceState)


{ super.onCreate(savedInstanceState);
...

class RunBackground extends Thread {


String userName; RunBackground(String
userName) { this.userName =
namapengguna;
}
public void run() { userInfo
= fetchUserInfo(namapengguna); Log.d
(TAG, info pengguna);
Log.d(TAG,"Jalankan di
utas"); coba {
final JSONObject jsonreader = new JSONObject(userInfo); Log.d
(TAG, jsonreader.toString());
runOnUiThread(New Thread() { Log.d
public void run() {
(TAG, "runOnUiThread");
txtUserInfo.setText(jsonreader.toString()); }
}
);
}

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

panggilan seperti userInfo.getString("id").

 Saat Anda berada di utas latar belakang, Anda tidak dapat


melakukan panggilan ke elemen ui mana pun, misalnya,
jika Anda ingin menyetel teks dari textView atau edittext,
Anda tidak akan dapat melakukannya.
untuk membuat perubahan pada elemen ui saat berjalan
di utas latar belakang, Anda harus kembali ke utas ui; dan
cara melakukannya adalah dengan memanggil metode
runOnUiThread() . metode runOnUiThread() mengambil
objek thread sebagai parameter; timpa run() , dan di
sanalah Anda menulis kode untuk membuat perubahan
pada ui (seperti yang ditunjukkan di sini).
. sekarang kita dapat menulis hasil panggilan github ke textView

Sekarang, jalankan aplikasi baik di emulator atau perangkat dan coba


ambil info GitHub Anda sendiri.

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.

Anda mungkin juga menyukai