Temui RxJava: Pustaka Pemrograman Reaktif yang Hilang untuk Android

Diterbitkan: 2022-03-11

Jika Anda seorang pengembang Android, kemungkinan besar Anda pernah mendengar tentang RxJava. Ini adalah salah satu perpustakaan yang paling banyak dibahas untuk mengaktifkan Pemrograman Reaktif dalam pengembangan Android. Ini disebut-sebut sebagai kerangka kerja masuk untuk menyederhanakan tugas konkurensi/asinkron yang melekat dalam pemrograman seluler.

Tapi… apa itu RxJava dan bagaimana cara “menyederhanakan” sesuatu?

Pemrograman Reaktif Fungsional untuk Android: Pengantar RxJava

Lepaskan Android Anda dari terlalu banyak utas Java dengan RxJava.
Menciak

Meskipun ada banyak sumber daya yang sudah tersedia secara online yang menjelaskan apa itu RxJava, dalam artikel ini tujuan saya adalah memberi Anda pengenalan dasar tentang RxJava dan secara khusus bagaimana RxJava cocok dengan pengembangan Android. Saya juga akan memberikan beberapa contoh konkret dan saran tentang bagaimana Anda dapat mengintegrasikannya dalam proyek baru atau yang sudah ada.

Mengapa Mempertimbangkan RxJava?

Pada intinya, RxJava menyederhanakan pengembangan karena meningkatkan tingkat abstraksi seputar threading. Artinya, sebagai pengembang Anda tidak perlu terlalu khawatir tentang detail tentang cara melakukan operasi yang seharusnya terjadi pada utas yang berbeda. Ini sangat menarik karena threading sulit untuk diperbaiki dan, jika tidak diterapkan dengan benar, dapat menyebabkan beberapa bug yang paling sulit untuk di-debug dan diperbaiki.

Memang, ini tidak berarti RxJava antipeluru dalam hal threading dan tetap penting untuk memahami apa yang terjadi di balik layar; namun, RxJava pasti dapat membuat hidup Anda lebih mudah.

Mari kita lihat sebuah contoh.

Panggilan Jaringan - RxJava vs AsyncTask

Katakanlah kita ingin mendapatkan data melalui jaringan dan memperbarui UI sebagai hasilnya. Salah satu cara untuk melakukannya adalah dengan (1) membuat subkelas AsyncTask bagian dalam di Activity / Fragment kami, (2) melakukan operasi jaringan di latar belakang, dan (3) mengambil hasil dari operasi itu dan memperbarui UI di utas utama .

 public class NetworkRequestTask extends AsyncTask<Void, Void, User> { private final int userId; public NetworkRequestTask(int userId) { this.userId = userId; } @Override protected User doInBackground(Void... params) { return networkService.getUser(userId); } @Override protected void onPostExecute(User user) { nameTextView.setText(user.getName()); // ...set other views } } private void onButtonClicked(Button button) { new NetworkRequestTask(123).execute() }

Meskipun kelihatannya tidak berbahaya, pendekatan ini memiliki beberapa masalah dan keterbatasan. Yaitu, kebocoran memori/konteks mudah dibuat karena NetworkRequestTask adalah kelas dalam dan dengan demikian menyimpan referensi implisit ke kelas luar. Juga, bagaimana jika kita ingin menyambungkan operasi panjang lainnya setelah panggilan jaringan? Kami harus membuat sarang dua AsyncTask s yang secara signifikan dapat mengurangi keterbacaan.

Sebaliknya, pendekatan RxJava untuk melakukan panggilan jaringan mungkin terlihat seperti ini:

 private Subscription subscription; private void onButtonClicked(Button button) { subscription = networkService.getObservableUser(123) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<User>() { @Override public void call(User user) { nameTextView.setText(user.getName()); // ... set other views } }); } @Override protected void onDestroy() { if (subscription != null && !subscription.isUnsubscribed()) { subscription.unsubscribe(); } super.onDestroy(); }

Dengan menggunakan pendekatan ini, kami memecahkan masalah (kebocoran memori potensial yang disebabkan oleh utas berjalan yang memegang referensi ke konteks luar) dengan menyimpan referensi ke objek Subscription yang dikembalikan. Objek Subscription ini kemudian diikat ke metode #onDestroy() objek Activity / Fragment untuk menjamin bahwa operasi Action1#call tidak dijalankan saat Activity / Fragment perlu dihancurkan.

Juga, perhatikan bahwa tipe #getObservableUser(...) (yaitu Observable<User> ) dirantai dengan panggilan lebih lanjut ke sana. Melalui API yang lancar ini, kami dapat memecahkan masalah kedua dalam menggunakan AsyncTask yaitu memungkinkan panggilan jaringan lebih lanjut/rantai operasi yang lama. Cukup rapi, ya?

Mari selami lebih dalam beberapa konsep RxJava.

Observable, Observer, dan Operator - 3 O dari RxJava Core

Di dunia RxJava, semuanya dapat dimodelkan sebagai aliran. Aliran memancarkan item dari waktu ke waktu, dan setiap emisi dapat dikonsumsi/diamati.

Jika Anda memikirkannya, aliran bukanlah konsep baru: acara klik dapat menjadi aliran, pembaruan lokasi dapat menjadi aliran, pemberitahuan push dapat menjadi aliran, dan sebagainya.

Di dunia RxJava, semuanya dapat dimodelkan sebagai aliran.

Abstraksi aliran diimplementasikan melalui 3 konstruksi inti yang saya suka menyebutnya "3 O"; yaitu: O bservable, O bserver, dan O perator. Observable memancarkan item (aliran); dan Pengamat mengkonsumsi barang-barang itu. Emisi dari objek Observable selanjutnya dapat dimodifikasi, diubah, dan dimanipulasi dengan merantai panggilan Operator .

Tampak

Observable adalah abstraksi aliran di RxJava. Ini mirip dengan Iterator dalam hal itu, diberikan urutan, iterate melalui dan menghasilkan item-item secara teratur. Seorang konsumen kemudian dapat mengkonsumsi barang-barang tersebut melalui antarmuka yang sama, terlepas dari urutan yang mendasarinya.

Katakanlah kita ingin mengeluarkan angka 1, 2, 3, dalam urutan itu. Untuk melakukannya, kita dapat menggunakan metode Observable<T>#create(OnSubscribe<T>) .

 Observable<Integer> observable = Observable.create(new Observable.OnSubscribe<Integer>() { @Override public void call(Subscriber<? super Integer> subscriber) { subscriber.onNext(1); subscriber.onNext(2); subscriber.onNext(3); subscriber.onCompleted(); } });

Memanggil subscriber.onNext(Integer) memancarkan item dalam aliran dan, ketika aliran selesai memancarkan, subscriber.onCompleted() kemudian dipanggil.

Pendekatan untuk membuat Observable ini cukup bertele-tele. Untuk alasan ini, ada metode praktis untuk membuat instance Observable yang harus disukai di hampir semua kasus.

Cara paling sederhana untuk membuat Observable adalah menggunakan Observable#just(...) . Seperti yang disarankan oleh nama metode, itu hanya memancarkan item yang Anda berikan ke dalamnya sebagai argumen metode.

 Observable.just(1, 2, 3); // 1, 2, 3 will be emitted, respectively

Pengamat

Komponen berikutnya dari aliran yang Dapat Diobservasi adalah Pengamat (atau Pengamat) yang berlangganan. Pengamat diberitahu setiap kali sesuatu yang "menarik" terjadi di aliran. Pengamat diberitahu melalui acara berikut:

  • Observer#onNext(T) - dipanggil saat item dipancarkan dari aliran
  • Observable#onError(Throwable) - dipanggil ketika terjadi kesalahan dalam aliran
  • Observable#onCompleted() - dipanggil saat aliran selesai memancarkan item.

Untuk berlangganan streaming, cukup panggil Observable<T>#subscribe(...) dan berikan instance Observer.

 Observable<Integer> observable = Observable.just(1, 2, 3); observable.subscribe(new Observer<Integer>() { @Override public void onCompleted() { Log.d("Test", "In onCompleted()"); } @Override public void onError(Throwable e) { Log.d("Test", "In onError()"); } @Override public void onNext(Integer integer) { Log.d("Test", "In onNext():" + integer); } });

Kode di atas akan memancarkan yang berikut di Logcat:

 In onNext(): 1 In onNext(): 2 In onNext(): 3 In onNext(): 4 In onCompleted()

Mungkin juga ada beberapa contoh di mana kita tidak lagi tertarik pada emisi Observable. Ini sangat relevan di Android ketika, misalnya, Activity / Fragment perlu diambil kembali dalam memori.

Untuk berhenti mengamati item, kita hanya perlu memanggil Subscription#unsubscribe() pada objek Subscription yang dikembalikan.

 Subscription subscription = someInfiniteObservable.subscribe(new Observer<Integer>() { @Override public void onCompleted() { // ... } @Override public void onError(Throwable e) { // ... } @Override public void onNext(Integer integer) { // ... } }); // Call unsubscribe when appropriate subscription.unsubscribe();

Seperti yang terlihat dalam cuplikan kode di atas, setelah berlangganan Observable, kami menyimpan referensi ke objek Langganan yang dikembalikan dan kemudian memanggil subscription#unsubscribe() bila perlu. Di Android, ini paling baik dipanggil dalam Activity#onDestroy() atau Fragment#onDestroy() .

Operator

Item yang dipancarkan oleh Observable dapat diubah, dimodifikasi, dan disaring melalui Operator sebelum memberi tahu objek Observer yang berlangganan. Beberapa operasi paling umum yang ditemukan dalam pemrograman fungsional (seperti peta, filter, pengurangan, dll.) juga dapat diterapkan ke aliran yang dapat diamati. Mari kita lihat peta sebagai contoh:

 Observable.just(1, 2, 3, 4, 5).map(new Func1<Integer, Integer>() { @Override public Integer call(Integer integer) { return integer * 3; } }).subscribe(new Observer<Integer>() { @Override public void onCompleted() { // ... } @Override public void onError(Throwable e) { // ... } @Override public void onNext(Integer integer) { // ... } });

Cuplikan kode di atas akan mengambil setiap emisi dari Observable dan mengalikan masing-masing dengan 3, menghasilkan aliran masing-masing 3, 6, 9, 12, 15. Menerapkan Operator biasanya mengembalikan Observable lain sebagai hasilnya, yang nyaman karena ini memungkinkan kita untuk menghubungkan beberapa operasi untuk mendapatkan hasil yang diinginkan.

Mengingat aliran di atas, katakanlah kami hanya ingin menerima angka genap. Ini dapat dicapai dengan merantai operasi filter .

 Observable.just(1, 2, 3, 4, 5).map(new Func1<Integer, Integer>() { @Override public Integer call(Integer integer) { return integer * 3; } }).filter(new Func1<Integer, Boolean>() { @Override public Boolean call(Integer integer) { return integer % 2 == 0; } }).subscribe(new Observer<Integer>() { @Override public void onCompleted() { // ... } @Override public void onError(Throwable e) { // ... } @Override public void onNext(Integer integer) { // ... } });

Ada banyak operator built-in RxJava toolset yang memodifikasi aliran Observable; jika Anda dapat memikirkan cara untuk memodifikasi aliran, kemungkinan besar, ada Operator untuk itu. Tidak seperti kebanyakan dokumentasi teknis, membaca dokumen RxJava/ReactiveX cukup sederhana dan langsung. Setiap operator dalam dokumentasi dilengkapi dengan visualisasi tentang bagaimana Operator memengaruhi aliran. Visualisasi ini disebut "diagram marmer."

Berikut cara Operator hipotetis yang disebut flip dapat dimodelkan melalui diagram marmer:

Contoh bagaimana Operator hipotetis yang disebut flip dapat dimodelkan melalui diagram marmer.

Multithreading dengan RxJava

Mengontrol utas di mana operasi terjadi dalam rantai Observable dilakukan dengan menentukan Penjadwal di mana operator harus terjadi. Pada dasarnya, Anda dapat menganggap Penjadwal sebagai kumpulan utas yang, jika ditentukan, akan digunakan dan dijalankan oleh operator. Secara default, jika Penjadwal tersebut tidak disediakan, rantai Observable akan beroperasi pada utas yang sama di mana Observable#subscribe(...) dipanggil. Jika tidak, Penjadwal dapat ditentukan melalui Observable#subscribeOn(Scheduler) dan/atau Observable#observeOn(Scheduler) di mana operasi terjadwal akan terjadi pada thread yang dipilih oleh Scheduler.

Perbedaan utama antara kedua metode adalah bahwa Observable#subscribeOn(Scheduler) menginstruksikan sumber Observable Penjadwal mana yang harus dijalankan. Rantai akan terus berjalan pada utas dari Penjadwal yang ditentukan di Observable#subscribeOn(Scheduler) hingga panggilan ke Observable#observeOn(Scheduler) dibuat dengan Scheduler yang berbeda. Ketika panggilan seperti itu dilakukan, semua pengamat mulai dari sana (yaitu, operasi selanjutnya di rantai) akan menerima pemberitahuan dalam utas yang diambil dari observeOn Scheduler.

Berikut adalah diagram marmer yang menunjukkan bagaimana metode ini memengaruhi tempat operasi dijalankan:

Diagram marmer yang menunjukkan bagaimana metode ini memengaruhi tempat operasi dijalankan.

Dalam konteks Android, jika operasi UI perlu dilakukan sebagai akibat dari operasi yang lama, kami ingin operasi itu dilakukan di thread UI. Untuk tujuan ini, kita dapat menggunakan AndroidScheduler#mainThread() , salah satu Penjadwal yang disediakan di perpustakaan RxAndroid.

RxJava di Android

Sekarang kita memiliki beberapa dasar di bawah ikat pinggang kita, Anda mungkin bertanya-tanya — apa cara terbaik untuk mengintegrasikan RxJava dalam aplikasi Android? Seperti yang Anda bayangkan, ada banyak kasus penggunaan untuk RxJava tetapi, dalam contoh ini, mari kita lihat satu kasus khusus: menggunakan objek yang dapat diamati sebagai bagian dari tumpukan jaringan.

Dalam contoh ini, kita akan melihat Retrofit, klien HTTP yang bersumber terbuka dari Square yang memiliki binding bawaan dengan RxJava untuk berinteraksi dengan API GitHub. Secara khusus, kami akan membuat aplikasi sederhana yang menyajikan semua repositori berbintang untuk pengguna yang diberi nama pengguna GitHub. Jika Anda ingin melompat ke depan, kode sumber tersedia di sini.

Buat Proyek Android Baru

  • Mulailah dengan membuat proyek Android baru dan beri nama GitHubRxJava .

Tangkapan layar: Buat proyek Android baru

  • Di layar Target Perangkat Android , tetap pilih Ponsel dan Tablet dan setel level SDK minimum 17. Jangan ragu untuk menyetelnya ke level API yang lebih rendah/lebih tinggi, tetapi untuk contoh ini, API level 17 sudah cukup.

Tangkapan layar: Targetkan layar Perangkat Android

  • Pilih Empty Activity di prompt berikutnya.

Tangkapan layar: Tambahkan Aktivitas ke layar Seluler

  • Pada langkah terakhir, pertahankan Nama Aktivitas sebagai MainActivity dan buat file layout activity_main .

Tangkapan layar: Sesuaikan layar Aktivitas

Pengaturan Proyek

Sertakan RxJava, RxAndroid, dan library Retrofit di app/build.gradle . Perhatikan bahwa menyertakan RxAndroid secara implisit juga menyertakan RxJava. Namun, ini adalah praktik terbaik untuk selalu menyertakan kedua pustaka tersebut secara eksplisit karena RxAndroid tidak selalu berisi versi RxJava terbaru. Menyertakan versi terbaru RxJava secara eksplisit menjamin penggunaan versi terbaru.

 dependencies { compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'io.reactivex:rxandroid:1.2.0' compile 'io.reactivex:rxjava:1.1.8' // ...other dependencies }

Buat Objek Data

Buat kelas objek data GitHubRepo . Kelas ini merangkum repositori di GitHub (respons jaringan berisi lebih banyak data tetapi kami hanya tertarik pada sebagian dari itu).

 public class GitHubRepo { public final int id; public final String name; public final String htmlUrl; public final String description; public final String language; public final int stargazersCount; public GitHubRepo(int id, String name, String htmlUrl, String description, String language, int stargazersCount) { this.id = id; this.name = name; this.htmlUrl = htmlUrl; this.description = description; this.language = language; this.stargazersCount = stargazersCount; } }

Retrofit Pengaturan

  • Buat antarmuka GitHubService . Kami akan meneruskan antarmuka ini ke Retrofit dan Retrofit akan membuat implementasi GitHubService .
 public interface GitHubService { @GET("users/{user}/starred") Observable<List<GitHubRepo>> getStarredRepositories(@Path("user") String userName); }
  • Buat kelas GitHubClient . Ini akan menjadi objek yang akan berinteraksi dengan kita untuk melakukan panggilan jaringan dari level UI.

    • Saat membuat implementasi GitHubService melalui Retrofit, kita perlu meneruskan RxJavaCallAdapterFactory sebagai adaptor panggilan sehingga panggilan jaringan dapat mengembalikan objek Observable (melewati adaptor panggilan diperlukan untuk panggilan jaringan apa pun yang mengembalikan hasil selain Call ).

    • Kita juga perlu memasukkan GsonConverterFactory agar kita dapat menggunakan Gson sebagai cara untuk menyusun objek JSON ke objek Java.

 public class GitHubClient { private static final String GITHUB_BASE_URL = "https://api.github.com/"; private static GitHubClient instance; private GitHubService gitHubService; private GitHubClient() { final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); final Retrofit retrofit = new Retrofit.Builder().baseUrl(GITHUB_BASE_URL) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson)) .build(); gitHubService = retrofit.create(GitHubService.class); } public static GitHubClient getInstance() { if (instance == null) { instance = new GitHubClient(); } return instance; } public Observable<List<GitHubRepo>> getStarredRepos(@NonNull String userName) { return gitHubService.getStarredRepositories(userName); } }

Tata Letak Pengaturan

Selanjutnya, buat UI sederhana yang menampilkan repo yang diambil dengan memasukkan nama pengguna GitHub. Buat activity_home.xml - tata letak untuk aktivitas kita - dengan sesuatu seperti berikut:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android: android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android: android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:hint="@string/username"/> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/search"/> </LinearLayout> </LinearLayout>

Buat item_github_repo.xml - tata letak item ListView untuk objek repositori GitHub - dengan sesuatu seperti berikut:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="6dp"> <TextView android: android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="24sp" android:text tools:text="Cropper"/> <TextView android: android:layout_width="match_parent" android:layout_height="wrap_content" android:lines="2" android:ellipsize="end" android:textSize="16sp" android:layout_below="@+id/text_repo_name" tools:text="Android widget for cropping and rotating an image."/> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/text_repo_description" android:layout_alignParentLeft="true" android:textColor="?attr/colorPrimary" android:textSize="14sp" android:text tools:text="Language: Java"/> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/text_repo_description" android:layout_alignParentRight="true" android:textColor="?attr/colorAccent" android:textSize="14sp" android:text tools:text="Stars: 1953"/> </RelativeLayout>

Rekatkan Semuanya Bersama

Buat ListAdapter yang bertanggung jawab untuk mengikat objek GitHubRepo ke dalam item ListView . Proses ini pada dasarnya melibatkan item_github_repo.xml menjadi View jika tidak ada View daur ulang yang disediakan; jika tidak, View yang didaur ulang akan digunakan kembali untuk mencegah terlalu banyak objek View yang menggembung.

 public class GitHubRepoAdapter extends BaseAdapter { private List<GitHubRepo> gitHubRepos = new ArrayList<>(); @Override public int getCount() { return gitHubRepos.size(); } @Override public GitHubRepo getItem(int position) { if (position < 0 || position >= gitHubRepos.size()) { return null; } else { return gitHubRepos.get(position); } } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { final View view = (convertView != null ? convertView : createView(parent)); final GitHubRepoViewHolder viewHolder = (GitHubRepoViewHolder) view.getTag(); viewHolder.setGitHubRepo(getItem(position)); return view; } public void setGitHubRepos(@Nullable List<GitHubRepo> repos) { if (repos == null) { return; } gitHubRepos.clear(); gitHubRepos.addAll(repos); notifyDataSetChanged(); } private View createView(ViewGroup parent) { final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); final View view = inflater.inflate(R.layout.item_github_repo, parent, false); final GitHubRepoViewHolder viewHolder = new GitHubRepoViewHolder(view); view.setTag(viewHolder); return view; } private static class GitHubRepoViewHolder { private TextView textRepoName; private TextView textRepoDescription; private TextView textLanguage; private TextView textStars; public GitHubRepoViewHolder(View view) { textRepoName = (TextView) view.findViewById(R.id.text_repo_name); textRepoDescription = (TextView) view.findViewById(R.id.text_repo_description); textLanguage = (TextView) view.findViewById(R.id.text_language); textStars = (TextView) view.findViewById(R.id.text_stars); } public void setGitHubRepo(GitHubRepo gitHubRepo) { textRepoName.setText(gitHubRepo.name); textRepoDescription.setText(gitHubRepo.description); textLanguage.setText("Language: " + gitHubRepo.language); textStars.setText("Stars: " + gitHubRepo.stargazersCount); } } }

Rekatkan semuanya menjadi satu di MainActivity . Ini pada dasarnya adalah Activity yang ditampilkan saat kami pertama kali meluncurkan aplikasi. Di sini, kami meminta pengguna untuk memasukkan nama pengguna GitHub mereka, dan akhirnya, menampilkan semua repositori yang berkilau bintangnya dengan nama pengguna tersebut.

 public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private GitHubRepoAdapter adapter = new GitHubRepoAdapter(); private Subscription subscription; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ListView listView = (ListView) findViewById(R.id.list_view_repos); listView.setAdapter(adapter); final EditText editTextUsername = (EditText) findViewById(R.id.edit_text_username); final Button buttonSearch = (Button) findViewById(R.id.button_search); buttonSearch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String username = editTextUsername.getText().toString(); if (!TextUtils.isEmpty(username)) { getStarredRepos(username); } } }); } @Override protected void onDestroy() { if (subscription != null && !subscription.isUnsubscribed()) { subscription.unsubscribe(); } super.onDestroy(); } private void getStarredRepos(String username) { subscription = GitHubClient.getInstance() .getStarredRepos(username) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<GitHubRepo>>() { @Override public void onCompleted() { Log.d(TAG, "In onCompleted()"); } @Override public void onError(Throwable e) { e.printStackTrace(); Log.d(TAG, "In onError()"); } @Override public void onNext(List<GitHubRepo> gitHubRepos) { Log.d(TAG, "In onNext()"); adapter.setGitHubRepos(gitHubRepos); } }); } }

Jalankan Aplikasi

Menjalankan aplikasi harus menampilkan layar dengan kotak input untuk memasukkan nama pengguna GitHub. Pencarian kemudian akan menampilkan daftar semua repo yang berkilau bintangnya.

Tangkapan layar aplikasi yang menampilkan daftar semua repo yang berkilau bintangnya.

Kesimpulan

Saya harap ini berfungsi sebagai pengantar yang berguna untuk RxJava dan gambaran umum tentang kemampuan dasarnya. Ada banyak sekali konsep yang kuat di RxJava dan saya mendorong Anda untuk menjelajahinya dengan menggali lebih dalam ke wiki RxJava yang terdokumentasi dengan baik.

Jangan ragu untuk meninggalkan pertanyaan atau komentar di kotak komentar di bawah. Anda juga dapat mengikuti saya di Twitter di @arriolachris di mana saya banyak men-tweet tentang RxJava dan semua hal tentang Android.

Jika Anda menginginkan sumber belajar yang komprehensif tentang RxJava, Anda dapat melihat ebook yang saya tulis dengan Angus Huang di Leanpub.

Terkait: Sepuluh Fitur Kotlin Untuk Meningkatkan Pengembangan Android