Intro to RxAndroid

RxAndroid ဆိုတာ ဘာလဲ မပြောခင် RxJava အကြောင်းက စရမယ် ထင်ပါတယ်။ RxJava ဆိုတာကတော့ ReactiveX ရဲ့ extension library တစ်ခုပါ။ RxAndroid က RxJava ကိုမှ Android အတွက် ထပ်ပြီး extend လုပ်ထားပါ။ Reactive programming ရဲ့ သဘောက ကျွန်တော်နားလည်သလောက်ကတော့ အလုပ်တစ်ခုပြီးလို့ ရလာတဲ့ ရလာဒ်ပေါ် မူတည်ပြီး နောက်တစ်ခုကို ဆက်တိုက် (chain sequence) လုပ်ဆောင်လို့ရသလို၊ thread တွေခွဲပြီး တချိန်တည်း တစ်ပြိုင်နက် (concurrence) လုပ်ဆောင်လို့ရပါတယ်။ ဒါက programmer တွေအတွက် ရေးသားရတာ ပိုမိုရှင်းလင်းပြီး လွယ်ကူတယ်။ ဒါပေမဲ့ ကျွန်တော်တို့လို Functional Programming ကို နားမလည်တဲ့လူတွေအတွက် RxAndroid စလုပ်ရင် အခက်အခဲတွေ အတော်များပါတယ်။ ဒီ postကတော့ စပြီးလေ့လာချင်တဲ့အတွက် လွယ်ကူစေဖို့ပါ။

Rx မှာ အဓိကကျတာကတော့ Observable နဲ့ Subscriber ပါ။ Observable က အလုပ်ကို လုပ်ဆောင်ပြီး Subscriber ကို အကြောင်းကြားလေ့ရှိပါတယ်။ Observable က လုပ်ဆောင်လိုက်တဲ့ အရာဟာ အောင်မြင်လို့ ပြီးသွားတာ ဖြစ်ချင် ဖြစ်မယ်၊ ဒါမှမဟုတ် error တက်ပြီး ပြီးသွားတာလည်း ဖြစ်မယ်။ ဘယ်လိုပဲဖြစ်ဖြစ် ပြီးတာနဲ့ Observable က Subscriber ရဲ့ onNext() methodကို လှမ်းခေါ်ပါတယ်။ ပြီးမှ onCompleted() ဒါမှမဟုတ် onError() ခေါ်ပါတယ်။ အောင်မြင်လို့ ပြီးသွားတာဆိုရင် onNext() ကနေ onCompleted ကို ရောက်မှာ ဖြစ်ပြီး error တက်ခဲ့ရင်တော့ onError ပါ။ သူ့ရဲ့ pattern အရ Observable က Subscriber မရှိပဲ ဘယ်တော့မှ​ အလုပ်မလုပ်ပါဘူး။ တကယ်လို့ RxAndroid အကြောင်းကို ရေရေလည်လည် နားလည်ချင်ရင်တော့ Grokking RxJava, Part 1: The Basicsမှာ လေ့လာကြည့်ပါ။

ဒီ RxSunshine project မှာတော့ ကျွန်တော်တို့ သုံးနေကြဖြစ်တဲ့ Retrofit ကို RxAndroid နဲ့ ပ​ေါင်း အသုံးပြုပုံလေး ရေးထားပါတယ်။ ဒါက အရင် GDG Yangonရဲ့ Android Bootcampတွေမှာ ပြောပြနေကြဖြစ်တဲ့ Sunshine ကို RxAndroid နဲ့ Retrofit နဲ့ပြင်ရေးထားပါ။ တကယ်လို့ Retrofit နဲ့ သိပ်အကျွမ်းတဝင် မရှိဘူးဆိုရင် Retrofit အလွယ်တကူ အသုံးပြုနည်းမှာ သွားလေ့လာကြည့်ပါ။

ပထမဆုံး Android Project အသစ်တစ်ခုကို Activity With Fragmentနဲ့ ဖန်တီးလိုက်ပါ။ ကျွန်တော်ကတော့ MainActivity နဲ့ MainFragment လို့ပဲ နာမည် ပေးထားပါတယ်။ ပြီးရင် appရဲ့ build.gradle မှာ လိုအပ်တဲ့ libraryတွေ အောက်ပါအတိုင်း ထည့်ပေးပါ။

gradle sync လည်း ပြီးလို့ ရေးလို့ ရပြီဆိုရင်တော့ အရင်ဆုံး Config ဆိုတဲ့ class လေး တစ်ခု ဖန်တီးပါမယ်။ ဒီ class ထဲမှာ ကျွန်တော်တို့ project တစ်ခုလုံးမှာ သုံးမည့် ဘယ်တော့မှ မပြင်မည့် values တွေ ရေးလေ့ရှိပါတယ်။ ဒီမှာတော့ api နဲ့ သက်ဆိုင်တာတွေပါ။

WeatherApi ဆိုတဲ့ နာမည်နဲ့ class တစ်ခု ဖန်တီးလိုက်ပါ။

ပုံမှန် Retrofit ကိုသာသုံးမယ်ဆိုရင် အောက်ကလို WeatherService ဆိုတဲ့ interface classထဲမှာ void method နဲ့ callback ကို အသုံးပြုရမှာပါ။

ဒါဆိုရင် Retrofit ကလည်း background thread မှာ runပြီးတော့ success ဖြစ်ရင် UI thread မှာ update လုပ်တာပါပဲ။ ဘာလို့ RxJava ကို သုံးရမှာလည်းလို့ မေးစရာရှိတယ်။ Retrofit က error handling က network အတွက်ပါပဲ။ ဥပမာ server ကို လှမ်းခေါ်တယ် fail ဖြစ်တယ်။ Error handling method ထဲ ရောက်သွားတယ်။ success ဖြစ်တယ်။ success method မှာ UI update လုပ်မယ်။ အဲ့မှာ တက်တဲ့ error သူနဲ့ မဆိုင်တော့ဘူး။ Rx မှာတော့ success ဖြစ်ဖြစ် fail ဖြစ်ဖြစ် onNext ကိုသွားတယ်။ အဲ့ဒီကမှ onError (သို့) onCompleted ကိုသွားတယ်။ အဲ့ဒီအတွက် တခါတ​လေ JSON parsing error ဖြစ်တာ null ဖြစ်တာစတာတွေကိုပါ တစ်ခါထဲ ကိုင်တွယ်ပေးတယ်။ ဒီလို request တစ်ခုထဲဆို Rx ကို သုံးရတာ သိပ်မထူးခြားလှပေမဲ့ chain sequence အတွက်တော့ တော်တော်မိုက်ပါတယ်။ ဥပမာ user sign up လုပ်မယ် success ဆိုရင် sign in တန်းလုပ်မယ်။ Retrofit ဆိုရင်တော method နှစ်ခုရေးရမယ်။ Rxမှာတော့ flatMap လိုမျိုး သုံးလိုက်မယ်ဆိုရင် မျက်စိ အတော်ရှင်းပါတယ်။

fragment_main.xml မှာ ဒီလို ပြင်ထားပါတယ်။ Data ရက်အလိုက် list နဲ့ ပြဖို့ RecyclerView ၊ Error message ပြဖို့ TextView ရယ်၊ serverကနေ request တောင်းနေတုန်း ပြဖို့ ProgressBar ရယ် ထည့်ထားပါတယ်။ row တစ်ခုချင်းစီကို ပြဖို့အတွက် ListView မသုံးပဲ RecyclerView ကို သုံးထားပါတယ်။ အမှန်တော့ overdoing ပါပဲ။ ဒါပေမဲ့ RecyclerView သုံးနေကျ မဟုတ်တဲ့သူတွေလည်း သုံးဖြစ်သွားအောင်လို့ပါ။

ဒါကတော့ ရက်တစ်ခုချင်း Weather Forecast အတွက် layout ဖန်တီးပြီး အောက်ပါအတိုင်း ပြင်လိုက်ပါ။ Weather ပြတဲ့ icon အတွက် ImageView၊ စာအတွက် TextView ပါ။

အောက်က WeatherItem ဆိုတဲ့ classကတော့ image အတွက် name ရယ် Weather Forecast အတွက် ပြမဲ့စာအတွက် Object တစ်ခုဖန်တီးထားတာပါ။

ပြီးရင်တော့ RecyclerView အတွက် WeatherAdapter ဆိုနဲ့ နာမည်နဲ့ Adapter class create လုပ်ပြီး အောက်ကအတိုင်း ရေးလိုက်ပါ။

နောက်ဆုံးကတော့ ကျွန်တော်တို့ MainFragment ကို ပြင်ပါမယ်။

getWeather() ဆိုတဲ့ methodမှာ ကြည့်မယ်ဆိုရင် subscribeOn(Schedulers.newThread()) ဆိုတာက task ကို သပ်သပ် new thread အနေနဲ့ လုပ်ခိုင်းတာဖြစ်ပြီး၊ observeOn(AndroidSchedulers.mainThread()) ကတော့ Main UI thread မှာ အလုပ်လုပ်မယ်လို့ ပြောတာပါ။ တကယ်လို့ observeOn() သာ မပါဘူးဆိုရင် "The current thread must have a looper" ဆိုပြီး errorတက်မှာပါ။ ဆိုလိုတာကတော့ background thread ကနေ Main UI threadကို လှမ်း update လုပ်လို့ မရဘူး ဖြစ်သွားမှာပါ။ အပေါ်မှာ ပြောခဲ့သလိုပဲ Observable က မခိုင်းရင် မလုပ်ပါဘူး။ Subscribe လုပ်မှ လုပ်မှာပါ။ ဒါကြောင့် subscribe() ဆိုတဲ့ method ကို ခေါ်ပါတယ်။ Subscribe ကမှ new Observer ဆိုပြီး အပေါ်မှာ ပြောခဲ့တဲ့ callbacks သုံးခုကို ခေါ်ထားပါတယ်။ server ကနေ success ဖြစ်ရင် onNext() မှာ JSON parsing လုပ်ပါတယ်။ Parsing ပြီးသွားရင် onCompleted() မှာ Loading ProgressBar နဲ့ TextView ကို ဖျောက် list ကို ပြပါတယ်။ Error တက်ခဲ့မယ်ဆိုရင်တော့ onError() က TextView မှာ error message ကိုပြပြီး ProgressBar နဲ့ RecyclerView ကို ဖျောက်ပါတယ်။

အောက်ကပုံက observeOn ကို comment ပေးပြီး run တဲ့ပုံပါ။

ဒါကတော့ ပုံမှန်အတိုင်း run လိုက်ရင် ပေါ်မည့်ပုံပါ။

အထက်ပါ project ကို GitHub [Download zip] မှာ ရယူနိုင်ပါတယ်။ မေးမြန်းလိုသည်များကိုလည်း MMAUG Facebook Group မှာ မေးမြန်းနိုင်ပါတယ်။