آشنایی با برنامه نویسی واکنش گرا RxJava، RxAndroid در اندروید
RxJava مدتی هست که ایجاد شده و مردم در مورد قابلیت های بیشتر آن می شنوند ، اما بسیاری از آنها هنوز شروع به کار نکرده اند. اگر شما یکی از آنها هستید ، برای مهمانی دیر کرده اید ، اما این خوب است. دیر رسیدن بهتر از هرگز نرسیدن است. تعداد کمی از توسعه دهندگانی که با آنها صحبت کردم می گویند هیچ راهنمای مناسبی در دسترس نیست (ما می توانیم مقالات خوبی را در وب سایت های متعدد نسبت به یک مکان واحد پیدا کنیم) یا آنها از شروع کار جدید می ترسند.
در این مقاله ، من قصد دارم مجموعه ای از آموزش ها را که مباحث اولیه تا موضوعات پیشرفته را در RxJava و RxAndroid پوشش می دهد ، بنویسم.
امیدوارم این سری مقاله در هفته های آینده هر توسعه دهنده مبتدی را به توسعه دهنده RxAndroid مبدل کند.
ما با شرح تئوری های بنیادی در مورد چند اصطلاح که در برنامه نویسی واکنش گرا با آنها برخورد می کنید شروع می کنیم و بعداً به چند نمونه کد می پردازیم.
برنامه نویسی واکنش گرا (Reactive) چیست ؟
برنامه نویسی واکنش گرا اساساً برنامه نویسی ناهمزمان مبتنی بر رویداد است. هر چیزی که مشاهده می کنید یک جریان داده ناهمزمان است که می تواند مشاهده شود و هنگامی که مقادیری را منتشر می کند ، اقدامی انجام خواهد شد. می توانید از هر چیزی جریان داده ایجاد کنید. تغییرات متغیر ، رویدادهای کلیک ، پروتکل http ، ذخیره داده ها ، خطاها و موارد دیگر. هنگامی که می گویند ناهمزمان ، این بدان معناست که هر ماژول کد بر روی موضوع خاص خود اجرا می شود ، بنابراین چندین قطعه کد را به طور همزمان اجرا می کند.
مزیت رویکرد ناهمزمان این است که هر task بر روی thread خاص خود اجرا می شود ، همه taskها می توانند همزمان شروع شوند و مدت زمان لازم برای تکمیل همه taskها معادل کار طولانی تر در لیست است. وقتی صحبت از برنامه های تلفن همراه می شود ، task ها در thread پس زمینه اجرا می شود ، می توانید بدون مسدود کردن thread اصلی به تجربه کاربری یکپارچه برسید.
یک مثال ساده (از ویکی پدیا) x = y + z می باشد ؛ جایی که مجموع y و z به x اختصاص داده می شود. در برنامه نویسی واکنشی ، وقتی مقدار y تغییر می کند ، مقدار x بدون اجرای مجدد دستور x = y + z به طور خودکار به روز می شود.نتیجه را می توان با مشاهده مقدار y یا z دست آورد.
یک Array List می تواند یک جریان داده باشد و به ازای هر آیتمی که منتشر می شود اقدامی انجام شود. شاید بخواهید اعداد زوج را فیلتر کرده و اعداد فرد را نادیده بگیرید. در این حالت می توان با استفاده از حلقه های معمول و جملات شرطی انجام داد ، اما در برنامه نویسی واکنش گرا می توانید با رویکردی کاملاً متفاوت به نتیجه برسید.
وقتی برنامه خود را در برنامه نویسی واکنش گرا شروع می کنید ، نحوه طراحی معماری و نحوه نوشتن کد کاملاً تغییر می کند. حتی در صورت به کار بردن Clean Architecture ، MVP ، MVVM و سایر دیزاین پترن ها قدرتمندتر می شود.
Reactive Extensions (RX)
افزونه های واکنش گرا یا ReactiveXیا RX کتابخانه ای است که اصول برنامه نویسی واکنش گرا را دنبال می کند ، یعنی برنامه های ناهمزمان و مبتنی بر رویداد با استفاده از دنباله ای از observable می باشد. این کتابخانه ها مجموعه ای از interfaces ها و method ها را ارائه می دهند که به توسعه دهندگان در نوشتن کد تمیز و ساده کمک می کند.
برنامه های افزودنی واکنش گرا به چندین زبان C++ (RxCpp) ، C# (Rx.NET) ، جاوا (RxJava) ، Kotlin (RxKotlin) ، Swift (RxSwift) و موارد دیگر موجود است. ما به طور خاص به RxJava و RxAndroid علاقه مند هستیم زیرا Android مرکز توجه ما است.
RX Java چیست؟
Rxjava پیاده سازی جاوا از Reactive Extensions است (از شرکت Netflix) . اساساً کتابخانه ای است که با پیروی از الگوی Observer ، رویدادهای ناهمزمان را ترکیب می کند. شما می توانید جریان داده های ناهمزمان را در هر thread ایجاد کنید ، داده ها را تبدیل کرده و توسط Observer در هر thread استفاده کنید. این کتابخانه طیف وسیعی از اپراتورهای شگفت انگیز مانند map combine, merge, filter و موارد دیگر را ارائه می دهد که می تواند بر روی جریان داده اعمال شود.
وقتی کار بر روی نمونه های واقعی کد را شروع کنید ، اطلاعات بیشتری در مورد عملگرها و تغییرات خواهید داشت.
RxAndroid چیست؟
RxAndroid مختص پلتفرم اندروید با چند کلاس اضافه در بالای RxJava است. به طور خاص ، Schedulers در RxAndroid (AndroidSchedulers.mainThread ()) معرفی می شود که نقش مهمی در حمایت از مفهوم چند رشته ای در برنامه های اندرویدی ایفا می کند. Schedulers اساساً Threadرا که یک کد خاص بر روی آن اجرا می شود تصمیم می گیرد که آیا روی Thread زمینه یا Threadاصلی است. جدا از این ، همه مواردی که ما استفاده می کنیم فقط از کتابخانه RxJava است.
از طرفی Scheduler های زیادی موجود است ، Schedulers.io () و AndroidSchedulers.mainThread () به طور گسترده در برنامه نویسی اندروید استفاده می شوند. در زیر لیستی از Schedulers موجود و معرفی مختصری از آنها آمده است.
Schedulers.io () : این گزینه برای انجام عملیات بدون نیاز به CPU مانند برقراری تماس شبکه ، خواندن دیسک / فایل ، عملیات پایگاه داده و غیره استفاده می شود. همچنین مجموعه ای از Thread ها را حفظ می کند.
AndroidSchedulers.mainThread () : این گزینه امکان دسترسی به Main Thread / UI Thread را فراهم می کند. معمولاً عملیات مانند به روز رسانی UI ، تعاملات کاربر در این Thread اتفاق می افتد. ما نباید هیچ عملیات سنگین روی این Thread انجام دهیم زیرا باعث نقص در برنامه و یا ANR dialogمی شود.
Schedulers.newThread () – با استفاده از این ، هر بار که یک task زمانبندی می شود ، یک Thread جدید ایجاد می شود. معمولاً پیشنهاد می شود از Scheduler استفاده نکنید مگر اینکه عملیات بسیار طولانی انجام شود. Threadهای ایجاد شده از طریق newThread () دیگر مورد استفاده قرار نمی گیرند.
Schedulers.computation ()-از این Scheduler می توان برای انجام عملیات CPU مانند پردازش داده های عظیم ، پردازش bitmap و غیره استفاده کرد. تعداد Threadهای ایجاد شده با استفاده از این Scheduler کاملاً به تعداد هسته های CPU موجود بستگی دارد.
Schedulers.single () – این Scheduler تمام task ها را به ترتیبی که اضافه شده ، اجرا می کند.در این صورت می تواند در مواقع لزوم برای اجرای متوالی مورد نیاز استفاده شود.
Schedulers.immediate () – این Scheduler ،task را بلافاصله به صورت همزمان با مسدود کردن Threadاصلی اجرا می کند.
Schedulers.trampoline () – task ها را به صورت First In – First Out اجرا می کند. تمام taskهای برنامه ریزی شده با محدود کردن تعداد Threadهای پس زمینه یک ، یک به یک اجرا می شوند.
Schedulers.from () – این Scheduler ، به ما امکان می دهد با محدود کردن تعداد Thread هایی که باید ایجاد شوند ، یک Scheduler از یک اجرا کننده ایجاد کنیم. هنگامی که مخزن Threadها اشغال می شود ، taskها در صف قرار می گیرند.
اکنون ما مفاهیم اساسی مورد نیاز را داریم. بیایید با برخی از مفاهیم کلیدی RxJava شروع کنیم که همه باید از آنها مطلع باشند.
- مبانی RxJava: Observable, Observer :
RxJava دارای دو جزء کلیدی است: Observable و Observer. علاوه بر این موارد دیگری مانند Scheduler ، Operators و Subscription نیز وجود دارد.
Observable : یک جریان داده است که برخی کارها را انجام می دهد و داده ها را منتشر می کند.
Observer: بخش مقابل Observable است. داده های منتشر شده توسط Observable را دریافت می کند.
Subscription : پیوند بین Observable و Observer به را می گویند. می توان چندین Observer را با یک Observable ، Subscribe (پیوند) داد.
Operator / Transformation : Operator ها داده های منتشر شده توسط Observable را قبل از دریافت Observer تغییر می دهند.
Schedulers : Schedulers موضوعی را تعیین می کند که Observable باید بر روی آن داده ها را منتشر کند و Observer بر روی کدام داده ها را دریافت می کند ، یعنی background thread, main thread و غیره ،
مثال های پایه RxJava :
اکنون ما دانش تئوری خوبی در مورد برنامه نویسی واکنشی ، RxJava و RxAndroid داریم. بیایید به سراغ چند مثال با کد
برویم تا مفاهیم را بهتر درک کنیم.
افزودن وابستگی ها:
// RxJava
implementation "io.reactivex.rxjava2:rxjava:2.2.21"
// RxAndroid
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
مراحل اولیه:
- یک Observable ایجاد کنید که داده ها را منتشر می کند. در زیر ما یک Observable ایجاد کرده ایم که لیستی از نام حیوانات را منتشر می کند. در اینجا از عملگر just() برای انتشار چند نام حیوان استفاده می شود.
Observable<String> animalsObservable = Observable.just("Ant", "Bee", "Cat", "Dog", "Fox");
- یک Observer ایجاد کنید که به Observable گوش دهد. Observer روشهای رابط زیر را برای آگاهی از وضعیت Observable ارائه می دهد.
onSubscribe (): هنگامی که یک Observer در Observable مشترک (Subscribe) شود ، متد فراخوانی می شود.
onNext (): این متد زمانی فراخوانی می شود که Observable شروع به انتشار(Emitt) داده ها می کند.
onError (): در صورت بروز هرگونه خطا ، متد onError () فراخوانی می شود.
onComplete (): هنگامی که یک Observable انتشار تمام موارد را تکمیل می کند ، () Complete فراخوانی می شود.
Observer<String> animalsObserver = getAnimalsObserver();
private Observer<String> getAnimalsObserver() {
return new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
}
@Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "All items are emitted!");
}
};
}
3- Observer را در Observable مشترک (Subscribe)کنید تا بتواند دریافت داده ها را شروع کند. در اینجا ، می توانید دو روش دیگر را مشاهده کنید ، observOn () و subscribeOn ().
subscribeOn (Schedulers.io ()): این دستور به Observable می گوید که task را در یک background thread اجرا کند.
observOn (AndroidSchedulers.mainThread ()): این دستور به Observer می گوید که داده ها را در UI thread اندروید دریافت کند تا بتوانید هرگونه اقدام مرتبط با رابط کاربری را انجام دهید.
animalsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(animalsObserver);
اگر برنامه را اجرا کنید ، می توانید خروجی زیر را در LogCat خود مشاهده کنید.
onSubscribe
Name: Ant
Name: Bee
Name: Cat
Name: Dog
Name: Fox
All items are emitted!
با این حال ، شما فقط اولین برنامه RxJava خود را نوشتید. ما در مقاله های بعدی درباره Schedulers و Observers بیشتر می آموزیم. اما در حال حاضر این اطلاعات برای شروع کافی است.
مثال 1: Observable و Observer پایه
در اینجا کد کامل مثال بالا آمده است. activity را اجرا کرده و خروجی را در LogCat بررسی کنید.
public class Example1Activity extends AppCompatActivity {
/**
* Basic Observable, Observer, Subscriber example
* Observable emits list of animal names
*/
private static final String TAG = Example1Activity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example1);
// observable
Observable<String> animalsObservable = getAnimalsObservable();
// observer
Observer<String> animalsObserver = getAnimalsObserver();
// observer subscribing to observable
animalsObservable
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(animalsObserver);
}
private Observer<String> getAnimalsObserver() {
return new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
}
@Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "All items are emitted!");
}
};
}
private Observable<String> getAnimalsObservable() {
return Observable.just("Ant", "Bee", "Cat", "Dog", "Fox");
}
}
خروجی
onSubscribe
Name: Ant
Name: Bee
Name: Cat
Name: Dog
Name: Fox
All items are emitted!
مثال 2: معرفی Disposable
در این مثال ما میخواهیم component جدیدی به نام Disposable را معرفی نماییم.
Disposable : برای دور انداختن(dispose) اشتراک (subscription) استفاده می شود زمانی که Observer دیگر نمی خواهد به Observable گوش دهد. در اندروید Disposable برای جلوگیری از نشت حافظه (memory leaks) بسیار مفید است.
فرض کنید شما در حال برقراری تماس طولانی با شبکه هستید و UI را به روز می کنید. هنگامی که تماس شبکه کار خود را کامل می کند ، اگر activity یا fragment قبلاً از بین رفته باشد (destroy) ، در صورتی که اشتراک Observer هنوز پابرجاست و سعی می کند activity از بین رفته را به روز کند. در این حالت می تواند باعث نشت حافظه شود. بنابراین با استفاده از Disposable ، عدم اشتراک (un-subscription) می تواند زمانی باشد که activity از بین برود.
در مثال زیر مشاهده می کنید که از Disposable استفاده می شود و فراخوانی disposable.dispose () در onDestroy () اشتراک Observer را لغو می کند.
public class Example2Activity extends AppCompatActivity {
/**
* Basic Observable, Observer, Subscriber example
* Observable emits list of animal names
* You can see Disposable introduced in this example
*/
private static final String TAG = Example2Activity.class.getSimpleName();
private Disposable disposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example2);
// observable
Observable<String> animalsObservable = getAnimalsObservable();
// observer
Observer<String> animalsObserver = getAnimalsObserver();
// observer subscribing to observable
animalsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(animalsObserver);
}
private Observer<String> getAnimalsObserver() {
return new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
disposable = d;
}
@Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "All items are emitted!");
}
};
}
private Observable<String> getAnimalsObservable() {
return Observable.just("Ant", "Bee", "Cat", "Dog", "Fox");
}
@Override
protected void onDestroy() {
super.onDestroy();
// don't send events once the activity is destroyed
disposable.dispose();
}
}
این خروجی مشابه نمونه قبلی را ایجاد می کند.
مثال 3: معرفی Operator
اکنون با معرفی یک اپراتور برای تبدیل داده های منتشر شده ، مثال دیگری را خواهیم دید. در مثال زیر عملگر filter () برای فیلتر کردن داده های منتشر شده استفاده می شود.
عملگر filter () با اعمال یک عبارت شرطی داده ها را فیلتر می کند. داده هایی که شرایط را داشته باشند منتشر می شوند و بقیه نادیده گرفته می شوند.
در مثال زیر نام حیواناتی که با حرف `b` شروع می شوند فیلتر می شوند.
public class Example3Activity extends AppCompatActivity {
/**
* Basic Observable, Observer, Subscriber example
* Observable emits list of animal names
* You can see Disposable introduced in this example
*/
private static final String TAG = Example3Activity.class.getSimpleName();
private Disposable disposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example3);
// observable
Observable<String> animalsObservable = getAnimalsObservable();
// observer
Observer<String> animalsObserver = getAnimalsObserver();
// observer subscribing to observable
animalsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.filter(new Predicate<String>() {
@Override
public boolean test(String s) throws Exception {
return s.toLowerCase().startsWith("b");
}
})
.subscribeWith(animalsObserver);
}
private Observer<String> getAnimalsObserver() {
return new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
disposable = d;
}
@Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "All items are emitted!");
}
};
}
private Observable<String> getAnimalsObservable() {
return Observable.fromArray(
"Ant", "Ape",
"Bat", "Bee", "Bear", "Butterfly",
"Cat", "Crab", "Cod",
"Dog", "Dove",
"Fox", "Frog");
}
@Override
protected void onDestroy() {
super.onDestroy();
// don't send events once the activity is destroyed
disposable.dispose();
}
}
اگر مثال را اجرا کنید ، می توانید نام حیواناتی را که با حرف `b` شروع می شودکه در LogCat چاپ شده را مشاهده کنید.
onSubscribe
Name: Bat
Name: Bee
Name: Bear
Name: Butterfly
All items are emitted!
مثال 4: چند Observer و CompositeDisposable:
حالتی را در نظر بگیرید که چندین Observable و Observers دارید. دور انداختن(dispose) تک تک آنها در Destroy یک کار خسته کننده است و ممکن است مستعد خطا باشد زیرا ممکن است آنها را فراموش کرده باشید. در این حالت می توانیم از CompositeDisposable استفاده کنیم.
CompositeDisposable: می تواند لیست اشتراک ها را در یک جایگاهی نگهداری کند و می تواند همه آنها را به یکباره دور بیندازد(dispose).
معمولاً ما در متد onDestroy ، () compositeDisposable.clear صدا میزنیم ، اما می توانید در هر کجای کد آن را صدا بزنید.
در مثال زیر ، می توانید متوجه دو Observer ، animalObserver و animalsObserverAllCaps مشترک به همان Observable شوید. هر دو Observer داده های یکسانی دریافت می کنند اما داده ها با اعمال اپراتورهای مختلف در جریان تغییر می کنند.
animalsObserver: – عملگر filter () برای فیلتر کردن نام حیوانات با حرف `b` استفاده می شود.
animalsObserverAllCaps: – عملگر filter () برای فیلتر کردن نام حیوانات با حرف `c` استفاده می شود. بعداً از اپراتور map () برای اینکه نام هر حیوان تمام حروفش تبدیل به حروف بزرگ شود استفاده می شود. . استفاده از چند اپراتور در یک Observer ، واحد زنجیره ای از اپراتورها(chaining of operators) نامیده می شود.
public class Example4Activity extends AppCompatActivity {
/**
* Basic Observable, Observer, Subscriber example
* Observable emits list of animal names
* You can see filter() operator is used to filter out the
* animal names that starts with letter `b`
*/
private static final String TAG = Example4Activity.class.getSimpleName();
private CompositeDisposable compositeDisposable = new CompositeDisposable();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example4);
Observable<String> animalsObservable = getAnimalsObservable();
DisposableObserver<String> animalsObserver = getAnimalsObserver();
DisposableObserver<String> animalsObserverAllCaps = getAnimalsAllCapsObserver();
/**
* filter() is used to filter out the animal names starting with `b`
* */
compositeDisposable.add(
animalsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.filter(new Predicate<String>() {
@Override
public boolean test(String s) throws Exception {
return s.toLowerCase().startsWith("b");
}
})
.subscribeWith(animalsObserver));
/**
* filter() is used to filter out the animal names starting with 'c'
* map() is used to transform all the characters to UPPER case
* */
compositeDisposable.add(
animalsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.filter(new Predicate<String>() {
@Override
public boolean test(String s) throws Exception {
return s.toLowerCase().startsWith("c");
}
})
.map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return s.toUpperCase();
}
})
.subscribeWith(animalsObserverAllCaps));
}
private DisposableObserver<String> getAnimalsObserver() {
return new DisposableObserver<String>() {
@Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "All items are emitted!");
}
};
}
private DisposableObserver<String> getAnimalsAllCapsObserver() {
return new DisposableObserver<String>() {
@Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "All items are emitted!");
}
};
}
private Observable<String> getAnimalsObservable() {
return Observable.fromArray(
"Ant", "Ape",
"Bat", "Bee", "Bear", "Butterfly",
"Cat", "Crab", "Cod",
"Dog", "Dove",
"Fox", "Frog");
}
@Override
protected void onDestroy() {
super.onDestroy();
// don't send events once the activity is destroyed
compositeDisposable.clear();
}
}
اگر این مثال را اجرا کنید ، می توانید خروجی زیر را مشاهده کنید. در اینجا نام حیواناتی که با `B` شروع می شود توسط animalsObserver مشاهده می شود. همه اسامی که با حرف `c` شروع می شوند و با حروف بزرگ توسط animalsObserverAllCaps مشاهده می شوند.
Name: Bat
Name: Bee
Name: Bear
Name: Butterfly
All items are emitted!
Name: CAT
Name: CRAB
Name: COD
All items are emitted!
مثال 5: نوع داده سفارشی و اپراتورها :
در نهایت ما این مقاله را با یک مثال جالب به پایان می بریم. در این مقاله ، به جای استفاده از انواع داده های اولیه ، ما از نوع داده سفارشی یعنی مدل Note استفاده می کنیم. ما در اینجا از یک مفهوم Observable و Observer استفاده می کنیم مگر اینکه داده های جاری از نوع داده Note باشند.
در اینجا عملگر map () برای تبدیل همه یادداشت ها به تمام حروف بزرگ استفاده می شود.
public class Example4Activity extends AppCompatActivity {
/**
* Basic Observable, Observer, Subscriber example
* Introduced CompositeDisposable and DisposableObserver
* The observable emits custom data type (Note) instead of primitive data types
* ----
* .map() operator is used to turn the note into all uppercase letters
* ----
* You can also notice we got rid of the below declarations
* Observable<Note> notesObservable = getNotesObservable();
* DisposableObserver<Note> notesObserver = getNotesObserver();
*/
private static final String TAG = Example4Activity.class.getSimpleName();
private CompositeDisposable disposable = new CompositeDisposable();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example4);
// add to Composite observable
// .map() operator is used to turn the note into all uppercase letters
disposable.add(getNotesObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(new Function<Note, Note>() {
@Override
public Note apply(Note note) throws Exception {
// Making the note to all uppercase
note.setNote(note.getNote().toUpperCase());
return note;
}
})
.subscribeWith(getNotesObserver()));
}
private DisposableObserver<Note> getNotesObserver() {
return new DisposableObserver<Note>() {
@Override
public void onNext(Note note) {
Log.d(TAG, "Note: " + note.getNote());
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "All notes are emitted!");
}
};
}
private Observable<Note> getNotesObservable() {
final List<Note> notes = prepareNotes();
return Observable.create(new ObservableOnSubscribe<Note>() {
@Override
public void subscribe(ObservableEmitter<Note> emitter) throws Exception {
for (Note note : notes) {
if (!emitter.isDisposed()) {
emitter.onNext(note);
}
}
if (!emitter.isDisposed()) {
emitter.onComplete();
}
}
});
}
private List<Note> prepareNotes() {
List<Note> notes = new ArrayList<>();
notes.add(new Note(1, "buy tooth paste!"));
notes.add(new Note(2, "call brother!"));
notes.add(new Note(3, "watch narcos tonight!"));
notes.add(new Note(4, "pay power bill!"));
return notes;
}
class Note {
int id;
String note;
public Note(int id, String note) {
this.id = id;
this.note = note;
}
public int getId() {
return id;
}
public String getNote() {
return note;
}
public void setId(int id) {
this.id = id;
}
public void setNote(String note) {
this.note = note;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
disposable.clear();
}
}
خروجی
Id: 1, note: BUY TOOTH PASTE!
Id: 2, note: CALL BROTHER!
Id: 3, note: WATCH NARCOS TONIGHT!
Id: 4, note: PAY POWER BILL!
All notes are emitted!
امیدوارم این مقاله مقدمه خوبی در مورد RxJava به شما داده باشد.
1 دیدگاه
اولین کسی باشید که در مورد این مطلب اظهار نظر می کند.
واقعا نکات آموزندهای داشت. تشکر میکنم.