RxJava ile Tanışın: Android için Eksik Reaktif Programlama Kitaplığı
Yayınlanan: 2022-03-11Bir Android geliştiricisiyseniz, RxJava'yı duymuşsunuzdur. Android geliştirmede Reaktif Programlamayı etkinleştirmek için en çok tartışılan kitaplıklardan biridir. Mobil programlamanın doğasında bulunan eşzamanlılık/eşzamansız görevleri basitleştirmek için başvurulacak çerçeve olarak lanse edilir.
Ama… RxJava nedir ve işleri nasıl “basitleştirir”?
RxJava'nın ne olduğunu açıklayan birçok çevrimiçi kaynak mevcut olsa da, bu makalede amacım size RxJava'ya temel bir giriş yapmak ve özellikle Android geliştirmeye nasıl uyduğunu anlatmak. Ayrıca yeni veya mevcut bir projeye nasıl entegre edebileceğiniz konusunda bazı somut örnekler ve öneriler vereceğim.
Neden RxJava'yı Düşünmelisiniz?
Özünde, RxJava, iş parçacığı oluşturma etrafındaki soyutlama düzeyini yükselttiği için geliştirmeyi basitleştirir. Yani, bir geliştirici olarak, farklı iş parçacıklarında gerçekleşmesi gereken işlemlerin nasıl gerçekleştirileceğine dair ayrıntılar hakkında çok fazla endişelenmenize gerek yok. Bu, iş parçacığı oluşturmanın doğru olması zor olduğundan ve doğru şekilde uygulanmazsa, en zor bazı hataların ayıklanıp düzeltilmesine neden olabileceğinden özellikle çekicidir.
Elbette bu, iş parçacığı oluşturma söz konusu olduğunda RxJava'nın kurşun geçirmez olduğu anlamına gelmez ve sahne arkasında neler olduğunu anlamak yine de önemlidir; ancak, RxJava kesinlikle hayatınızı kolaylaştırabilir.
Bir örneğe bakalım.
Ağ Araması - RxJava vs AsyncTask
Diyelim ki ağ üzerinden veri almak ve bunun sonucunda kullanıcı arayüzünü güncellemek istiyoruz. Bunu yapmanın bir yolu, (1) Activity
/ Fragment
bir iç AsyncTask
alt sınıfı oluşturmak, (2) ağ işlemini arka planda gerçekleştirmek ve (3) bu işlemin sonucunu almak ve ana iş parçacığında UI'yi güncellemektir. .
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() }
Göründüğü kadar zararsız, bu yaklaşımın bazı sorunları ve sınırlamaları var. Yani, NetworkRequestTask
bir iç sınıf olduğundan ve bu nedenle dış sınıfa örtük bir referansa sahip olduğundan, bellek/bağlam sızıntıları kolayca oluşturulur. Ayrıca, şebeke aramasından sonra başka bir uzun işlemi zincirlemek istersek ne olur? Okunabilirliği önemli ölçüde azaltabilecek iki AsyncTask
s yerleştirmemiz gerekir.
Buna karşılık, bir ağ araması gerçekleştirmeye yönelik bir RxJava yaklaşımı şöyle görünebilir:
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(); }
Bu yaklaşımı kullanarak, döndürülen Subscription
nesnesine bir başvuru tutarak sorunu (dış bağlama bir başvuru tutan çalışan bir iş parçacığının neden olduğu olası bellek sızıntıları) çözeriz. Bu Subscription
nesnesi daha sonra Activity
/ Fragment
yok edilmesi gerektiğinde Action1#call
işleminin yürütülmemesini garantilemek için Activity
/ Fragment
nesnesinin #onDestroy()
yöntemine bağlanır.
Ayrıca, #getObservableUser(...)
dönüş türünün (yani bir Observable<User>
) daha fazla çağrıyla zincirlendiğine dikkat edin. Bu akıcı API aracılığıyla, AsyncTask
kullanmanın ikinci sorununu çözebiliyoruz, bu da daha fazla ağ çağrısına/uzun işlem zincirine izin vermesidir. Oldukça temiz, ha?
Bazı RxJava kavramlarına daha derinden dalalım.
Gözlenebilir, Gözlemci ve Operatör - RxJava Core'un 3 O'su
RxJava dünyasında her şey akış olarak modellenebilir. Bir akış, zaman içinde madde(ler) yayar ve her bir emisyon tüketilebilir/gözlemlenebilir.
Bunu düşünürseniz, akış yeni bir kavram değildir: tıklama olayları bir akış olabilir, konum güncellemeleri bir akış olabilir, anında iletme bildirimleri bir akış olabilir vb.
Akış soyutlaması, “3 O'lar” olarak adlandırmayı sevdiğim 3 temel yapı aracılığıyla uygulanır; yani: Gözlenebilir, O gözlemci ve O operatör . Gözlenebilir öğeler (akım) yayar; ve Observer bu öğeleri tüketir. Gözlenebilir nesnelerden gelen emisyonlar, Operatör çağrılarını zincirleyerek daha fazla değiştirilebilir, dönüştürülebilir ve manipüle edilebilir.
gözlemlenebilir
Bir Gözlenebilir, RxJava'daki akış soyutlamasıdır. Bir yineleyiciye benzer, çünkü bir sıra verildiğinde, bu öğeleri düzenli bir şekilde yineler ve üretir. Bir tüketici daha sonra bu öğeleri, temeldeki sıralamadan bağımsız olarak aynı arabirim üzerinden tüketebilir.
Diyelim ki 1, 2, 3 sayılarını bu sırayla yaymak istedik. Bunu yapmak için Observable<T>#create(OnSubscribe<T>)
yöntemini kullanabiliriz.
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(); } });
Abone.onNext subscriber.onNext(Integer)
öğesini çağırmak, akışta bir öğe yayar ve akış yaymayı bitirdiğinde, daha sonra abone.onCompleted subscriber.onCompleted()
çağrılır.
Bir Gözlenebilir oluşturmaya yönelik bu yaklaşım oldukça ayrıntılıdır. Bu nedenle, hemen hemen her durumda tercih edilmesi gereken Observable örnekleri oluşturmak için kolaylık yöntemleri vardır.
Bir Observable oluşturmanın en basit yolu Observable#just(...)
kullanmaktır. Yöntem adından da anlaşılacağı gibi, yalnızca içine ilettiğiniz öğeleri yöntem bağımsız değişkenleri olarak yayar.
Observable.just(1, 2, 3); // 1, 2, 3 will be emitted, respectively
Gözlemci
Observable akımının sonraki bileşeni, ona abone olan Observer (veya Observer)'dır. Yayında "ilginç" bir şey olduğunda gözlemciler bilgilendiriliyor. Gözlemciler aşağıdaki olaylar aracılığıyla bilgilendirilir:
-
Observer#onNext(T)
- akıştan bir öğe yayınlandığında çağrılır -
Observable#onError(Throwable)
- akışta bir hata oluştuğunda çağrılır -
Observable#onCompleted()
- akış öğeleri yaymayı bitirdiğinde çağrılır.
Bir akışa abone olmak için Observable<T>#subscribe(...)
ve bir Observer örneğini iletmeniz yeterlidir.
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); } });
Yukarıdaki kod, Logcat'te aşağıdakileri yayacaktır:
In onNext(): 1 In onNext(): 2 In onNext(): 3 In onNext(): 4 In onCompleted()
Bir Gözlenebilir'in emisyonlarıyla artık ilgilenmediğimiz bazı durumlar da olabilir. Bu, özellikle, örneğin bir Activity
/ Fragment
bellekte geri alınması gerektiğinde Android'de geçerlidir.
Öğeleri gözlemlemeyi durdurmak için, döndürülen Subscription nesnesinde Subscription#unsubscribe()
öğesini çağırmamız yeterlidir.
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();
Yukarıdaki kod parçacığında görüldüğü gibi, bir Observable'a abone olduktan sonra, döndürülen Subscription nesnesinin referansını tutarız ve daha sonra gerektiğinde subscription#unsubscribe()
ı çağırırız. Android'de bu en iyi Activity#onDestroy()
veya Fragment#onDestroy()
içinde çağrılır.
Şebeke
Bir Observable tarafından yayılan öğeler, abone olunan Observer nesnesine/nesnelerine bildirilmeden önce Operatörler aracılığıyla dönüştürülebilir, değiştirilebilir ve filtrelenebilir. İşlevsel programlamada bulunan en yaygın işlemlerden bazıları (harita, filtre, küçültme vb.) Gözlenebilir bir akışa da uygulanabilir. Örnek olarak haritaya bakalım:
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) { // ... } });
Yukarıdaki kod parçacığı, Gözlemlenebilir'den her emisyonu alacak ve her birini 3 ile çarparak sırasıyla 3, 6, 9, 12, 15 akışını üretecektir. Bir Operatör uygulamak, tipik olarak, sonuç olarak başka bir Gözlemlenebilir döndürür; bu, istenen sonucu elde etmek için birden çok işlemi zincirlememize izin verdiği için uygundur.
Yukarıdaki akış göz önüne alındığında, yalnızca çift sayıları almak istediğimizi varsayalım. Bu, bir filtre işlemini zincirleyerek başarılabilir.
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) { // ... } });
Gözlenebilir akışı değiştiren RxJava araç setinde yerleşik birçok operatör vardır; Akışı değiştirmenin bir yolunu düşünebiliyorsanız, muhtemelen bunun için bir Operatör vardır. Çoğu teknik belgenin aksine, RxJava/ReactiveX belgelerini okumak oldukça basit ve konuya yöneliktir. Belgelerdeki her operatör, Operatörün akışı nasıl etkilediğine ilişkin bir görselleştirme ile birlikte gelir. Bu görselleştirmelere “mermer diyagramlar” denir.
Flip olarak adlandırılan varsayımsal bir Operatörün mermer bir diyagram aracılığıyla nasıl modellenebileceği aşağıda açıklanmıştır:
RxJava ile çoklu kullanım
Gözlenebilir zincirde işlemlerin gerçekleştiği iş parçacığının kontrolü, içinde bir operatörün gerçekleşmesi gereken Zamanlayıcı belirlenerek yapılır. Esasen, bir Zamanlayıcıyı, belirtildiğinde bir operatörün kullanacağı ve üzerinde çalışacağı bir iş parçacığı havuzu olarak düşünebilirsiniz. Varsayılan olarak, böyle bir Zamanlayıcı sağlanmazsa, Gözlenebilir zincir, Observable#subscribe(...)
çağrıldığında aynı iş parçacığında çalışır. Aksi takdirde, bir Zamanlayıcı Observable#subscribeOn(Scheduler)
ve/veya Observable#observeOn(Scheduler)
aracılığıyla belirtilebilir, burada programlanan işlem Zamanlayıcı tarafından seçilen bir iş parçacığında gerçekleşecektir.
İki yöntem arasındaki temel fark, Observable#subscribeOn(Scheduler)
öğesinin, Observable kaynağına hangi Zamanlayıcı üzerinde çalışması gerektiğini bildirmesidir. Zincir, farklı bir Zamanlayıcı ile Observable#observeOn(Scheduler)
için bir çağrı yapılana kadar Observable#subscribeOn(Scheduler)
içinde belirtilen Zamanlayıcıdan gelen iş parçacığı üzerinde çalışmaya devam edecektir. Böyle bir çağrı yapıldığında, oradan itibaren tüm gözlemciler (yani zincirdeki sonraki işlemler) observeOn
Zamanlayıcısından alınan bir iş parçacığında bildirimler alacaktır.
İşte bu yöntemlerin işlemlerin yürütüldüğü yeri nasıl etkilediğini gösteren bir mermer diyagram:
Android bağlamında, uzun bir işlemin sonucu olarak bir UI işleminin gerçekleşmesi gerekiyorsa, bu işlemin UI iş parçacığında gerçekleşmesini isteriz. Bu amaçla, RxAndroid kitaplığında sağlanan Zamanlayıcılardan biri olan AndroidScheduler#mainThread()
kullanabiliriz.

Android'de RxJava
Artık bazı temel bilgilere sahip olduğumuza göre, merak ediyor olabilirsiniz — RxJava'yı bir Android uygulamasına entegre etmenin en iyi yolu nedir? Tahmin edebileceğiniz gibi, RxJava için birçok kullanım durumu vardır, ancak bu örnekte, belirli bir duruma bakalım: Gözlenebilir nesneleri ağ yığınının bir parçası olarak kullanmak.
Bu örnekte, GitHub'ın API'si ile etkileşim kurmak için RxJava ile yerleşik bağlamalara sahip, Square tarafından açık kaynaklı bir HTTP istemcisi olan Retrofit'e bakacağız. Spesifik olarak, GitHub kullanıcı adı verilen bir kullanıcı için tüm yıldızlı depoları sunan basit bir uygulama oluşturacağız. Devam etmek isterseniz kaynak kodu burada.
Yeni Bir Android Projesi Oluşturun
- Yeni bir Android projesi oluşturarak ve buna GitHubRxJava adını vererek başlayın.
- Hedef Android Cihazları ekranında, Telefon ve Tablet'i seçili tutun ve minimum SDK seviyesini 17 olarak ayarlayın. Bunu daha düşük/daha yüksek bir API seviyesine ayarlamaktan çekinmeyin, ancak bu örnek için API seviyesi 17 yeterli olacaktır.
- Sonraki istemde Boş Etkinlik'i seçin.
- Son adımda, Etkinlik Adını MainActivity olarak tutun ve bir düzen dosyası activite_main oluşturun.
Proje Kurulumu
app/build.gradle
içine RxJava, RxAndroid ve Retrofit kitaplığını ekleyin. RxAndroid'in dolaylı olarak RxJava'yı da içerdiğini unutmayın. Bununla birlikte, RxAndroid her zaman RxJava'nın en güncel sürümünü içermediğinden, bu iki kitaplığı her zaman açıkça eklemek en iyi uygulamadır. Açıkça en son RxJava sürümünün dahil edilmesi, en güncel sürümün kullanılmasını garanti eder.
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 }
Veri Nesnesi Oluştur
GitHubRepo
veri nesnesi sınıfını oluşturun. Bu sınıf GitHub'da bir depoyu kapsar (ağ yanıtı daha fazla veri içerir, ancak biz bunun yalnızca bir alt kümesiyle ilgileniyoruz).
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; } }
Kurulum Güçlendirme
-
GitHubService
arayüzünü oluşturun. Bu arabirimi Retrofit'e geçireceğiz ve Retrofit,GitHubService
bir uygulamasını oluşturacak.
public interface GitHubService { @GET("users/{user}/starred") Observable<List<GitHubRepo>> getStarredRepositories(@Path("user") String userName); }
GitHubClient
sınıfını oluşturun. Bu, UI seviyesinden ağ aramaları yapmak için etkileşimde bulunacağımız nesne olacaktır.Retrofit aracılığıyla
GitHubService
uygulamasını oluştururken, ağ çağrılarının Observable nesneleri döndürebilmesi için çağrı bağdaştırıcısı olarak birRxJavaCallAdapterFactory
gerekir (Call
dışında bir sonuç döndüren herhangi bir ağ çağrısı için bir çağrı bağdaştırıcısının geçirilmesi gerekir).Ayrıca Gson'u JSON nesnelerini Java nesnelerine sıralamanın bir yolu olarak kullanabilmemiz için bir
GsonConverterFactory
geçmemiz gerekiyor.
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); } }
Kurulum Düzenleri
Ardından, GitHub kullanıcı adı girişi verilen alınan depoları görüntüleyen basit bir kullanıcı arayüzü oluşturun. Activity_home.xml - activity_home.xml
düzenini - aşağıdakine benzer bir şeyle oluşturun:
<?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>
item_github_repo.xml
- GitHub deposu nesnesi için ListView
öğe düzeni - aşağıdakine benzer bir şeyle oluşturun:
<?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>
Her Şeyi Birlikte Yapıştırın
GitHubRepo
nesnelerini ListView
öğelerine bağlamaktan sorumlu bir ListAdapter
oluşturun. İşlem, geri dönüştürülmüş bir View
sağlanmadıysa, esasen item_github_repo.xml
bir View
şişirmeyi içerir; aksi takdirde, çok fazla View
nesnesinin aşırı şişirilmesini önlemek için geri dönüştürülmüş bir View
yeniden kullanılır.
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); } } }
MainActivity
her şeyi birbirine yapıştırın. Bu, esasen, uygulamayı ilk başlattığımızda görüntülenen Activity
. Burada, kullanıcıdan GitHub kullanıcı adını girmesini ve son olarak bu kullanıcı adına göre tüm yıldızlı depoları görüntülemesini istiyoruz.
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); } }); } }
Uygulamayı Çalıştır
Uygulamayı çalıştırmak, GitHub kullanıcı adını girmek için bir giriş kutusu içeren bir ekran sunmalıdır. Arama, daha sonra tüm yıldızlı depoların listesini sunmalıdır.
Çözüm
Umarım bu, RxJava'ya faydalı bir giriş ve temel yeteneklerine genel bir bakış olarak hizmet eder. RxJava'da tonlarca güçlü kavram var ve iyi belgelenmiş RxJava wiki'sini daha derinlemesine inceleyerek bunları keşfetmenizi tavsiye ediyorum.
Aşağıdaki yorum kutusuna herhangi bir soru veya yorum bırakmaktan çekinmeyin. Ayrıca beni Twitter'da, RxJava ve Android ile ilgili her şey hakkında çok tweet attığım @arriolachris adresinden takip edebilirsiniz.
RxJava hakkında kapsamlı bir öğrenme kaynağı istiyorsanız, Leanpub'da Angus Huang ile yazdığım e-kitaba göz atabilirsiniz.