مقدمه‌ای بر RxAndroid

آموزش RxJava RxAndroid Rx جاوا آر ایکس جاوا آر ایکس اندروید tutorial رایگان ویدیویی

سطح آموزش:  #پیشرفته

پیش‌نیاز

برای دنبال کردن این آموزش باید با دیزاین پترن‌هایی که قبلا آموزش دادم آشنایی داشته باشید. بخصوص Observer، Factory و Iterator رو باید بشناسید.

RxJava و RxAndroid چیست؟

RX مخفف Reactive Extension هست و یک کتابخونه‌ایه که ما ازش استفاده می‌کنیم تا داخل محیط اندروید بصورت reactive برنامه‌نویسی کنیم.

الان تقریبا تمام زبان‌ها این افزونه رو دارن مثلا ما RxPhp و RxGo و RxScala و… رو هم داریم.

پس در واقع ReactiveX ها یا Reactive Extensions افزونه‌هایی هستن برای زبان‌های مختلف برنامه نویسی که به اون زبان اضافه شده و امکان برنامه‌نویسی reactive رو فراهم میکنن.

برنامه‌نویسی Reactive یعنی چی؟

reactive به معنی واکنشی هست. در حالت عادی ما توی برنامه‌نویسی بصورت متوالی و غیر واکنشی کد می‌زنیم. مثلا فرض کنید یک کلاس user داریم و میخوایم وقتی مقدار score تغییر کرد، یک TextView رو آپدیت کنیم.

حالت عادی برای انجام این کار باید شناسایی کنیم چه زمانی امتیاز تغییر میکنه و اون موقع مقدار TextView رو هم تغییر بدیم. توی این روش بصورت متوالی بعد از تغییر مقدار score نوشته TextView رو بروز کردیم.

اما توی برنامه‌نویسی Reactive ما یک Observer یا مشاهده‌گر می‌نویسیم که مقدار score رو مشاهده میکنه و هروقت این مقدار تغییر کرد تابع تغییر TextView رو اجرا می‌کنه. توی این حالت ما به تغییر score واکنش نشون میدیم. لازم نیست هرجا score تغییر کرد textview رو هم تغییر بدیم فقط یکبار یک مشاهده‌گر تعریف می‌کنیم که هربار score تغییر کرد کاری که ما میخوایم رو انجام بده.

RxJava و RxAndroid چه تفاوتی دارند؟

داخل اندروید ما هم از RxJava و هم از RxAndroid استفاده می‌کنیم و از این نظر فرقی برای ما ندارن. از اونجایی که داخل اندروید ما کد جاوا می‌زنیم پس RxJava رو به راحتی می‌تونیم استفاده بکنیم. اما یکسری ویژگی‌هایی هم در اندروید هست که زبان جاوا نداره. برای این ویژگی‌ها RxAndroid کلاس‌هایی رو در نظر گرفته. مثلا توی اندروید ما نمیتونیم روی threadـه UI با سرور ارتباط برقرار کنیم. از طرفی android-ui-thread برای جاوا ناشناخته‌ست برای همین توی این مورد RxAndroid دسترسی به UI-Thread رو برامون فراهم میکنه.

مفاهیم در RxJava و RxAndroid

RxJava برپایه دو پترن Observer و Iterator ساخته شده و تمام مفاهیم پایه و کلیدی‌ که داره از همین دو پترن گرفته شده.

مفهوم observable و observer رو به همین شکل داریم.

به علاوه هر observable در واقع یک Iterator هست. به مثال زیر که من مستقیما از کتاب RxJava for Android App Development آوردم نگاه کنید:

دقیقا مثل iterator که بدون اینکه اطلاعاتی از ساختار داخلی‌ش بده عنصر بعدی رو برای ما آماده میکنه، Observable هم بدون اینکه اطلاعاتی از ساختارش بده عنصر بعدی رو برامون فراهم میکنه. با این تفاوت که iterator این کارو بصورت non-reactive انجام میده.

اما اینکه عنصر بعدی رو فراهم میکنه یعنی چی؟ مگه اصلا ما حرفی از عنصر زدیم تا حالا؟

عنصر که من گفتم هم میتونه یک عنصر به معنی واقعی باشه. فرض کنید در حال خوندن لیستی از اینترنت هستیم. با دریافت هر آیتم در واقع یک عنصر داریم. هم میتونه لیستی از وقایع باشه. مثلا کلیک کاربر یک واقعه‌ست.

توجه کنید که لیست میتونه یک یا صفر آیتم داشته باشه.

من به جای عنصر از stream استفاده میکنم. مثلا یک stream از کلیک‌ها رو میتونیم داشته باشیم. یا streamـی از اطلاعات که از اینترنت خونده میشه.

در واقع observable ساختاریه که این streamها رو برامون منتشر (emit) میکنه.

حالا چجوری آماده میکنه؟

خیلی شبیه به iterator. ما توی iterator با صدا کردن iterator.next آیتم بعدی رو فراخونی می‌کردیم. Observable سه تا متد داره:

OnNext: دقیقا مثل iterator وقتی streamـی برای منتشر کردن باشه onNext صدا میشه.

OnComplete: وقتی کار یک observable تموم میشه onComplete صدا میشه.

OnError: وقتی موقع کار یک observable مشکلی پیش میاد onError صدا میشه.

Scheduler چیست؟

احتمالا با Multi Threading آشنا هستید. اینکه تا جای ممکن پردازش‌ها رو در threadهای مختلف انجام بدیم که هم سرعت اجرای برنامه افزایش پیدا کنه هم از حداکثر توان پردازشی استفاده کنیم. توی پلتفرم‌هایی مثل اندروید هم که به طور پیش‌فرض برنامه روی threadـه ui داره اجرا میشه این کار باعث میشه بار بیش از حدی روی دوش این thread نیفته و لگ و کندی ایجاد نشه.

به علاوه که کاری مثل ارتباط با سرور اصلا روی thread اصلی امکان پذیر نیست و حتما باید توی background انجام بشه.

برای همه این مسائل توی RxJava مفهوم Scheduler مطرح شده. با استفاده از Scheduler ما به Observable میگیم که هرکاری رو روی چه تردی انجام بده. مثلا اگه قرار هست از اینترنت دیتا بخونی برو و یک thread پیدا کن و روی اون این کارو بکن. اگه قراره مقدار TextView رو آپدیت کنی روی ترد UI این کارو کن (یکی از فلسفه‌های وجود RxAndroid گفتیم همین دسترسی به ترد UIـه)

مثال ساده از کار Observable

گفتم که Observable در واقع یک stream کننده‌ست. فرض کنید یک Observable داریم که یک تعدادی عدد رو emit یا منتشر میکنه و بعد کارش تموم میشه.

7 عدد که توسط Observable منتشر شده‌اند

کدش چنین چیزی میشه:

اما Just چیه؟

observableها متدهای خیلی زیاد با پیچیدگی‌های مختلف دارن. و در واقع همین متدها هستن که ارزش استفاده از RxJava رو انقدر زیاد کردن. just به این معنیه که این observable فقط این اعداد رو منتشر میکنه و تمام!

وقتی observable به اون خط مشکی برسه یعنی کارش تموم شده و onComplete صدا میشه.

اگر هم موقع فراخوانی این ۷ عدد مشکلی پیش بیاد onError صدا میشه.

سوال: فرضکنید میخوایم کلیک شدن روی یک button رو با Observable بنویسیم. OnNext و OnComplete و OnError چه زمانی اجرا خواهند شد؟

پاسخ: یه جورایی هر کلیک مثل منتشر شدن این ۷ عدد هستن. با این تفاوت که جای هر عدد که یک integer هست یک کلیک داریم.

هر بار که یک کلیک جدید داشته باشیم یعنی یک data جدید داریم. یاد iterator بیفتید. iterator برای اینکه داده جدیدی رو در اختیارمون بذاره next رو صدا میکرد. اینجا هم با هر کلیک OnNext صدا میشه. یعنی کارهایی که میخوایم با هر کلیک انجام بدیم رو توی OnClickListener انجام میدیم.

در بسیاری از موارد عملا OnComplete هیچوقت صدا نمیشه. کلیک‌ها هم معمولا تو این موارد قرار میگیرن. ما تا وقتی که یک activity وجود داره میتونیم روی button کلیک کنیم و بعد هم که activity از بین رفت Button هم از بین میره پس عملا هیچوقت این کلیک‌ها تمومی ندارن. کلیک شدن کاری نیست که بخوام تموم بشه و هر زمانی ممکنه یک کلیک اتفاق بیفته و onNext صدا بشه. بنابراین عملا OnComplete نداریم.

OnError هم قاعدتا موقع کلیک پیش نمیاد. اما به هر دلیلی اگر خطایی اتفاق بیفته متد OnError صدا میشه.

استفاده از Filter در RxAndroid

فرض کنید بین همون ۷ تا عدد میخوایم اعداد زوج رو جدا کنیم. یعنی Observable اعداد یک تا ۷ رو stream میکنه و بعد ما با استفاده از یک فیلتر اونایی که میخوایم رو جدا و منتشر می‌کنیم.

مثال استفاده از فیلتر filter در RxJava

کدش همچین چیزی میشه (البته الان خیلی کاری به کد نداریم فقط برای اینکه چشمتون آشنا بشه):

آموزش استفاده واقعی از RxAndroid

تا الان سعی کردیم ببینیم که اساسا Observable توی RxJava چه هدفی داره و چطوری به این هدفش میرسه. حالا وقتشه ببینیم چطور میتونیم به طور عملی از این دانش استفاده کنیم.

  1. برای استفاده از RxJava یا RxAndroid گام‌های زیر رو طی می‌کنیم:
  2. یک Observable می‌سازیم
  3. دیتا‌های مورد نظر برای انتشار از طریق Observable رو آماده می‌کنیم (مثلا متد Just که آشنا شدیم). به انتشار داده emit میگن.
  4. یک Observer می‌سازیم.
  5. به Observer میگیم که تغییرات Observable رو مشاهده کن و هروقت Observable چیزی emit کرد یک سری کار انجام بده.
  6. به Observer و Observable رو به هم متصل می‌کنیم.

توجه کنید که filter که بالا مثال زدم یک task نیست که observer انجام بده. فیلتر روی stream قبل از emit شدن انجام میشه و بعد داده‌های فیلتر شده emit میشه. حالا ما میتونیم با یک observer به این داده‌ها گوش بدیم و مثلا چاپشون کنیم.

 

بیاید دوباره ۷ تا عدد رو emit کنیم و بعد هم بگیم کارمون تموم شده (در ادامه با کمی تغییر از کدهایی که در این منبع اومده استفاده میکنم).

ساخت Observable و emit دیتا

ساخت Observer

اتصال observer و observable

البته من قبل‌تر نشون دادم که با متد just هم میشه بدون این همه کد زدن observable رو درست کرد. اما خوبه که انواع متدهای مختلف و روش‌ها رو ببینید تا کم‌کم آشنایی پیدا کنید.

نتیجه‌گیری

این پست تازه آغاز کار با RxJava هست. کار با Rx خیلی ساده نیست و نیاز به دیدن کد و  تمرین زیاد داره. اگر چیز زیادی دستگیرتون نشده نگران نباشید. سعی کنید با خوندن مطالب مختلف توی اینترنت از زاویه‌های مختلف به مساله نگاه کنید. وقتی که عادت کنید از Rx استفاده کنید می‌بینید که خیلی سریع‌تر از حالت عادی میتونید کارهای خیلی پیچیده رو انجام بدید.

تو پست‌های بعدی یکمی بیشتر و از زاویه‌های جدیدتر به مساله می‌پردازیم.

پی‌نوشت: چون از این به بعد بیشتر مثال و کد می‌بینیم، اگر این پست و پیش‌نیازها رو خوندید و هنوز توی مفاهیم مشکل دارید کتابی که لینکشو گذاشتم رو بخونید. ضمنا این لینک (که من برای نوشتن بخش‌هایی از این پست ازش استفاده کردم) هم به نظرم خوبه. شما هم اگر لینکی دارید که فکر میکنید میتونه به دیگران کمک کنه که مفاهیم رو بهتر متوجه بشن تو کامنتا بگید.

پی‌نوشت۲: روح‌اله عزیز توی کامنتا یک لینکی از مجموعه آموزش‌های RxJava قرار داده که گلچین خوبی از آموزش‌های سطح اینترنت در این خصوص هست. برای اینکه شاید بعضیا به کامنتا سر نزنن بهتر دونستم لینکش رو داخل پست قرار بدم -> A complete guide to learn RxJava

8 دیدگاه برای “مقدمه‌ای بر RxAndroid

  1. ممنون بابت پستی که نوشتید. ولی بعضی جاها لازمه که کلمات دقیق انتخاب بشن چون توی انتقال مطلب تاثیر میزاره. جاهایی که به نظرم اشتباه نوشتید رو مینویسم اگر جایی رو اشتباه کردم بگین لطفا 🙂
    به علاوه هر observable در واقع یک Iterator هست. => این باید بشه هر observable در واقع یک Iterable هست و هر observer در واقع یک Iterator هست.
    در واقع observable ساختاریه که این streamها رو برامون منتشر (emit) میکنه. => میتونیم بگیم observable خودش یک stream از آیتم هاست و آیتم ها رو برامون منتشر (emit) میکنه

    1. ممنون از دقتتون. مورد اول ایرادتون وارد نیست چون observerها iterator نیستن بلکه callback هستن.
      مورد دوم هم حق باشماست از نوشته من این مسئله که Observable در واقع خودش stream هست برداشت نمیشه.

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *