در این مجموعه با برنامهنویسی ReativeX و همچنین زیرمجموعههای آن RxKotlin, RxJava, RxAndroid آشنایی کامل پیدا خواهیم کرد.
این مجموعه بر اساس نسخه پرطرفدار و پراستفاده 2 نوشته شده است، نسخه 3 به تازگی منتشر شده است که در مفاهیم پایه و پیادهسازی مشابه همین نسخه میباشد.
امیدوارم با خوندن این پستها بگی این از اون آموزشی که توی Medium بود خیلی بهتره! هر چند که پستهای من قبل انتشار توی اینجا، ابتدا توی Medium نوشته میشن و اینبار تصمیم گرفتم اولویت انتشار اینجا باشه.
یک API برای برنامهنویسی نامتقارن میباشد که از دادههای قابل مشاهده استفاده میکند. ReactiveX ترکیبی از Observer Pattern و Iterator Pattern به همراه مفاهیم Functional Programming میباشد.
اگر متوجه مفهوم ReactiveX نشدید نگران نباشید از عنوان بعدی همه چیز ساده میشود.
یک رستوران را در نظر بگیرید، این رستوران قطعا شامل یک آشپزخانه برای پخت و تهیه غذا میشود. برای اینکه شما غذای خود را از آشپزخانه دریافت کنید چه واسطی این کار را انجام میدهد؟ قطعا خود شما به آشپزخانه نمیروید تا غذا را دریافت کنید، یا حتی آشپز به سر میز شما با سینی غذا نخواهد آمد، در صورتی که رستورانی با این مشخصات میشناسید حتما در قسمت نظرات بیان کنید :) این کار وظیفه واسطی به نام گارسون، مهماندار یا پیشخدمت میباشد.
کلمه API مخفف عبارت Application Programming Interface میباشد که معنی واسط برنامهنویسی اپلیکیشن را میدهد و در طول توسعه اپلیکیشنهای موبایلی، دسکتاپ و وب همواره ما در حال استفاده از آنها میباشیم.
لطفا این Interface را با ساختار Interface که در اکثر زبانهای برنامهنویسی وجود دارد اشتباه نگیرید، اینجا Interface به معنی واسط منظور ماست و هیچ نسبتی با زبانهای برنامهنویسی ندارد.
در طول توسعه اپلیکیشنهای موبایلی شما نیاز داشتهاید که به دیتابیس آنلاین اتصال شوید و اطلاعات را از آن دریافت کنید، چگونه این کار را انجام میدهید؟
فرض کنید در یک ایستگاه قطار قدیمی ایستادهاید و تمامی مسافران در یک صف پشت هم انتظار میکشند تا مامور قطار بلیط آنها را گرفته تا بتوانند سوار قطار شوند. تا زمانی که افراد جلوی شما سوار قطار نشده باشند، شما نمیتوانید سوار شوید و همچنین افراد قبل از شما نمیتوانند همزمان یا جلوتر از شما سوار شوند.
در برنامهنویسی متقارن تا زمانی که خط کد قبلی به صورت کامل اجرا نشده خط بعدی حق اجرا شدن ندارد.
نمونه کد برنامهنویسی متقارن - Github Gist
حالا در نظر بگیرید اگر قرار باشد اپلیکیشن ما یک کار محاسباتی سنگین، دریافت اطلاعات از دیتابیس و یا ارسال اطلاعات کاربر از طریق API را داشته باشد و همزان نیاز باشد که با کلیک کاربر بر روی دکمه عملیات دیگری صورت بگیرد. در این صورت با کلیک شدن دکمه در صورتی که فرآیند محاسباتی سنگین هم در حال انجام باشد کاربر با کندی اپلیکیشن رو به رو خواهد شد.
جاوا از Thread (رشته) برای انجام برنامهنویسی نامتقارن استفاده میکند تا کارهای سنگین در پسزمینه (Background) انجام شوند. در هر برنامه یک Thread اصلی برای کارهای مربوط به UI و Eventهای آن وجود دارد که در صورت انجام کارهای سنگین بر روی آن با گیرهای اپلیکیشن مواجه میشویم.
در صورتی که اطلاعاتی در این مورد ندارید بهترین کار Bookmark کردن این صفحه و شروع به آشنایی با مفاهیم Thread - Runnable- Synchronization میباشد. پیشنهاد من مطالعهی کتاب Head First Java میباشد.
کتابخانه Retrofit2 که از شناختهترینهای دنیای برنامهنویسی اندروید میباشد به صورت خودکار HTTP Requestهای شما را در پس زمینه و بر روی یک Thread جداگانه اجرا میکند. AsyncTask یکی دیگر از نمونههای شناخته شده برای انجام کار در Thread جداگانه میباشد.
نمونه کد برنامهنویسی نامتقارن با Thread ها - Github Gist
هر بار که کد بالا را اجرا کنید خروجی متفاوتی میگیرید به این دلیل که هیچکس جز JVM بر اساس منطق خود نمیتواند تصمیم بگیرید که کدام Thread اجرا خواهد شد و چه مدت در حال اجرا خواهد بود.
نمونه خروجی کد:
Thread: Thread[main,5,main] - 1 Thread: Thread[Thread-1,5,main] - 1 Thread: Thread[Thread-0,5,main] - 1 Thread: Thread[Thread-1,5,main] - 2 Thread: Thread[Thread-1,5,main] - 3 Thread: Thread[Thread-1,5,main] - 4 Thread: Thread[main,5,main] - 2 Thread: Thread[Thread-1,5,main] - 5 Thread: Thread[Thread-0,5,main] - 2 Thread: Thread[Thread-1,5,main] - 6 Thread: Thread[main,5,main] - 3 Thread: Thread[Thread-1,5,main] - 7 Thread: Thread[Thread-0,5,main] - 3 Thread: Thread[Thread-0,5,main] - 4 Thread: Thread[Thread-1,5,main] - 8 Thread: Thread[main,5,main] - 4 Thread: Thread[Thread-1,5,main] - 9 Thread: Thread[Thread-0,5,main] - 5 Thread: Thread[Thread-0,5,main] - 6 Thread: Thread[Thread-0,5,main] - 7 Thread: Thread[Thread-1,5,main] - 10 Thread: Thread[Thread-0,5,main] - 8 Thread: Thread[main,5,main] - 5 Thread: Thread[main,5,main] - 6 Thread: Thread[main,5,main] - 7 Thread: Thread[main,5,main] - 8 Thread: Thread[main,5,main] - 9 Thread: Thread[main,5,main] - 10 Thread: Thread[Thread-0,5,main] - 9 Thread: Thread[Thread-0,5,main] - 10
لطفا بحث Thread های جاوایی را با Core و Thread های CPU اشتباه نگرید. بحث این دو کاملا جداست، در جاوا Thread ها را میسازیم و JVM از OS برای اجرای آنها کمک میگیرد و این OS است که تصمیم میگیرید که کدام Thread بر روی کدام Core از CPU شما و کدام Thread آن CPU اجرا شود.
Java Threads != CPU Threads
قبل از توضیح این مورد نیاز است با دو الگوی برنامهنویسی Imperative و Declarative آشنا شویم:
فرض کنید با خانواده وارد یک رستوران شیک و شلوغ شدهاید چند راه برای انتخاب صندلی و مکان نشستن دارید؟ یکی اینکه بگویید من و خانواده آن میز شماره N را میخواهیم (Imperative - دستوری) را میخواهیم، یا اینکه میتوانید بگوید لطفا یک میز خانوادگی برای نشستن به ما بدهید (Declarative - اعلانی).
زبانهای برنامهنویسی جدید همانند Kotlin و Swift و همچنین نسخههای جدید Java علاوه بر OOP بودن از سبک Functional هم پشتیبانی میکنند.
نمونه کد برنامهنویسی Functional در Kotlin و نحوه پیادهسازی - Github Gist
در ReactiveX به سبک Functional یا همان Declarative (اعلانی) اطلاعات را درخواست میکنیم.
یکی از الگوهای طراحی (Design Pattern) های معروف که در دسته Behavioral Pattern ها قرار میگیرد. Behavioral Pattern دستهای از الگوهای طراحی میباشند که نحوه به ایجاد راه حلی برای پیادهسازی بهینه الگوریتمها و تخصیص وظیفه به هر کدام از Object ها در برنامه میپردازند.
فرض کنید یک شهر کوچک نشریهای پرطرفدار وجود دارد و برخی از مردم علاقهمند به دریافت نسخه جدید آن نشریه در درب منزل هستند. آیا نشریه روزنامه را برای تمامی اعضای آن شهر ارسال خواهد کرد؟ در این صورت بسیاری مردم که خواهان آن نشریه نبودهاند ناراضی خواهند بود و پولی بابت آن پرداخت نخواهند کرد. راه حل مناسبتر این است که نشریه از مردم بخواهد که خود درخواست عضویت بدهند و هرگاه که دیگر تمایلی به دریافت نسخههای جدید را نداشتند عضویت خود را باطل کنند.
اصطلاح دیگر Publisher/Subscriber مفهوم Observer (مشاهدهگر) و Observable (مشاهدهشونده) میباشد.
به رابطه بین Observer/Subscriber با Observable/Publisher کلمه Subscription (عضویت) اختصاص داده شده.
برای یادگیری کامل این الگوی طراحی که بسیار توصیه میگردد از این مقاله دنبال کنید.
یادگیری این Design Pattern به هیچ عنوان واجب نبوده و افراد علاقهمند میتوانند از این مقاله با مفاهیم کامل آن آشنا شوند.
کتابخانه RxKotlin همان RxJava میباشد که برخی Extensionها برای راحتی کار به آن اضافه شده است، در نتیجه تفاوتی چشمگیری با هم ندارند. همچنین RxAndroid شامل کلاسهای اضافه برای کار با RxJava بر روی سیستم عامل Android و استفاده از Main Thread آن میباشد.
با استفاده از RxKotlin کارهای سنگین مانند خواندن فایل و ذخیره اطلاعات را با استفاده از RxKotlin انجام میدهیم. بسیاری از کتابخانههای معروف همانند Retrofit و Room از این کتابخانه پشتیبانی میکنند.
شما میتوانید از ReactiveX بر روی زبانهای دیگر نیز استفاده کنید، از جمله:
قسمت اول - Observable
رفتن به پست
قسمت دوم - انواع Observableها
رفتن به پست