Android Lifecycle-Aware components

Google I/O’da tanฤฑtฤฑlan ve aslฤฑnda biz Android geliลŸtiricileri oldukรงa heyecanlandฤฑran en รถnemli geliลŸmelerden biri de Lifecyle-Aware Component’lerdi. Ben de yeni hakkฤฑnda detaylฤฑ bir yazma fฤฑrsatฤฑ bulabiliyorum. 22 Temmuz’da Google Dome’da GDG Istanbul olarak gerรงekleลŸtireceฤŸimiz codelab’in konularฤฑndan biri de bu componentler. Merak edenlerle hep beraber inceleyebiliriz.

Componentlerin detaylarฤฑnฤฑ konuลŸmaya baลŸlamadan Android Activity Lifecycle’ฤฑ bir hatฤฑrlamakta fayda var. AลŸaฤŸฤฑdaki imaj aslฤฑnda bize tรผm akฤฑลŸฤฑ รถzetlemiลŸ oluyor. Activity launch edildiฤŸinde sฤฑrasฤฑyla onCreate(Activity’nin yaratฤฑldฤฑฤŸฤฑ state), onStart(Activity’nin kullanฤฑcฤฑya visible olduฤŸu state), onResume methodlarฤฑ trigger ediliyor ve Activity run edilmiลŸ oluyor. EฤŸer รผzerinde baลŸka bir activity aรงฤฑlฤฑrsa, baลŸka bir app’e giderse vs onPause methodu รงaฤŸrฤฑlฤฑyor. Activity sistem tarafฤฑndan sonlanฤฑyorsa ise onPause ardฤฑndan, onStop(Activity tamamen gรถrรผnmez olur) ve onDestroy methodlarฤฑ da tetikleniyor. EฤŸer ki memory ihtiyacฤฑ sebebiyle sonlanmฤฑลŸsa onDestroy’a girmeden sonlanฤฑp tekrar aรงฤฑldฤฑฤŸฤฑndan en baลŸtan, yani onCreate’den sรผreรง baลŸlฤฑyor. Ancak baลŸka bir Activity aรงmak ya da farklฤฑ bir app’e geรงip geri gelmek iรงin Acitivity’den รงฤฑkฤฑldฤฑysa en baลŸtan create edilmeyeceฤŸi iรงin onCreate’e girmeyecektir. Bu durumda onResume’dan devam eder. Bu sebeple eฤŸer ki onPause’da activity’den รงฤฑktฤฑฤŸฤฑ iรงin yaptฤฑฤŸฤฑmฤฑz bir ลŸey var ise, bunun karลŸฤฑlฤฑฤŸฤฑna onResume’da dikkat etmemiz gerekir. onPause’la ilgili bir baลŸka dikkat etmemiz gereken nokta Android 7’yle beraber multiwindow geldiฤŸinden beri sadece bir tek acitivity aynฤฑ anda focus alabileceฤŸi iรงin biri focus aldฤฑฤŸฤฑnda diฤŸerinin onPause’a dรผลŸecek olmasฤฑdฤฑr. Aynฤฑ zamanda Activity’imizin รผzerine bir diyalog aรงฤฑldฤฑฤŸฤฑnda da gรถrรผnmesine raฤŸmen focus รผzerinde olmayacaฤŸฤฑ iรงin onPause methoduna girecektir. Tabiki bu methodlarฤฑn hepsini implement etmek zorunda deฤŸiliz ama yapฤฑlan iลŸin ne kadar kompleks olduฤŸuna gรถre hangilerinin implement edilmesi gerektiฤŸi deฤŸiลŸecektir, bunun iรงin de her birinin ne zaman trigger edildiฤŸini detaylฤฑ olarak bilmek รงok รถnemlidir.

https://developer.android.com/guide/components/activities/activity-lifecycle.html

Peki o zaman Architecture componentlerin neden kullanmalฤฑyฤฑz, niรงin hayatฤฑmฤฑza girdi dersek. Bu componentler, data tutarlฤฑlฤฑฤŸฤฑnฤฑ, lifecycle’ฤฑ yรถnetmemize yardฤฑmcฤฑ olmayฤฑ, uygulamamฤฑzฤฑn modรผler olmasฤฑ, memory leak’lerden kaรงฤฑnmamฤฑza ve tekrar eden kodlardan kurtulmamฤฑza yardฤฑmcฤฑ olmayฤฑ amaรงlฤฑyor. Tabi ki daha รถnce de her birimiz รงeลŸitli yollarla bunu saฤŸlฤฑyorduk. Bu bazen bir lib kullanmak bazense kendi geliลŸtirdiฤŸimiz bir รงรถzรผm olabiliyordu.

Livedata temel olarak datadaki deฤŸiลŸiklikleri izlememizi saฤŸlayan observable bir data holderdฤฑr. Data deฤŸiลŸikliklerindeki bizi notify eder, bรถylece ui’ฤฑ deฤŸiลŸtirebiliriz. Livedata abstract class’dฤฑr, extend edebilir ya da MutableLiveData’yฤฑ kullanabiliriz. LiveData’yฤฑ Room‘la beraber kullandฤฑฤŸฤฑmฤฑzda ise daha iyi sonuรงlar elde edebiliriz. Livedata kullanฤฑmฤฑna รถrnek ekranda gรถsterdiฤŸimiz listenin datanฤฑn deฤŸiลŸtiฤŸinde RecyclerView’i otomatik update etmesi olabilir mesela. LiveData LifeCycle aware bir componentdir. Aslฤฑnda en รถnemli รถzelliฤŸi de burada karลŸฤฑmฤฑza รงฤฑkฤฑyor. ร‡รผnkรผ daha รถnce benzeri geliลŸtirmeler yaptฤฑฤŸฤฑmฤฑzda yaลŸabileceฤŸimiz crashlerin Android’in kendisi tarafฤฑndan handle edilmesini saฤŸlฤฑyor. Lifecycle-aware demekle yazฤฑnฤฑn baลŸฤฑndaki Activity’yi รถrnek alarak รผzerine konuลŸtuฤŸumuz state’leri dรผลŸรผnebileceฤŸiniz gibi fragmentleri, servisleri de dรผลŸรผnebilirsiniz. ลžรถyle รถzetleyebiliriz; Livedata activity’nizin ekranda mฤฑ, deฤŸil mi yoksa tamamen destroy mu olduฤŸunu bilir ve updateleri buna gรถre gรถnderir. Bunun iรงin ise iki interface vardฤฑr. Biri lifecycle owners, activity’ler, fragmentler; diฤŸeri ise livecycle observers, livecycle owner’ฤฑ izleyip, lifecycle observerslarฤฑ notifiy eder. UI componentleri LiveData’yฤฑ, LiveData da LifeCycleOwner’larฤฑ observe eder.

Peki geriye bir tek ลŸey kalฤฑyor. Artฤฑk bizim componentlerimiz de Activity, Fragment’in state’lerinden haberdar ancak, รถrneฤŸin her konfigรผrasyon deฤŸiลŸikliฤŸinde, telefonu rotate ettiฤŸimizde de yeniden LiveData’nฤฑn create olmamasฤฑ datayฤฑ korumasฤฑ gerekir. Bunu da ViewModel‘le yapฤฑyoruz. Bunun iรงin de Activity’imiz iรงin gerekli olan tรผm datayฤฑ tutacaฤŸฤฑmฤฑz bir class yaratฤฑp bunu AndroidViewModel’den extends etmemiz gerekir.

Her bir senaryo iรงin mรผkemmel รงalฤฑลŸacak bir mimari kurmak biraz zor olabilir ama architecture components’i developer.android‘de anlatฤฑldฤฑฤŸฤฑ ลŸekilde aรงฤฑklamaya รงalฤฑลŸacaฤŸฤฑm.

Daha รถnce de yazdฤฑฤŸฤฑm gibi, ViewModel Activity,Fragment iรงin gerekli olan datanฤฑn tutulmasฤฑndan sorumlu olacak. Ancak sorumluluฤŸu bununla sฤฑnฤฑrlฤฑ kalฤฑr. Activity, Fragment’in recreation’larฤฑndan, konfigรผrasyon deฤŸiลŸikliklerinden etkilenmez.

Bu durumda รถrneฤŸin bir kullanฤฑcฤฑ sayfamฤฑz olacaksa, bunun activity ya da fragment ve xml’ine ek olarak bir de ViewModel sฤฑnฤฑfฤฑmฤฑz olacak.

Bu arada yine developer.android’de yazฤฑlana gรถre ลŸu an bu yapฤฑ stabil olmadฤฑฤŸฤฑ iรงin eฤŸer kullanmak istiyorsak, LifecycleFragment’den extend ederek kullanmamฤฑz gerekiyor. Ama stabil olduktan sonra Fragment’den extend etmemiz yeterli olacakmฤฑลŸ.

ลžu an 3 modรผlรผmรผz oldu. Bunlarฤฑ nasฤฑl baฤŸlayacaฤŸฤฑmฤฑzฤฑn cevabฤฑ ise LiveData. LiveData observable bir object. Data deฤŸiลŸikliklerinde UI’ฤฑ trigger ediyor. ร–ncesinde bunu kendi geliลŸtirdiฤŸimiz รงeลŸitli yรถntemlerle ya da RxJava gibi kรผtรผphanelerle saฤŸlฤฑyorduk. LiveData’yla ilgili de en muhteลŸem ลŸey lifecycle-aware olmasฤฑ. ฤฐhtiyaรง olmadฤฑฤŸฤฑnda referanslarฤฑnฤฑ otomatik olarak temizlenmesi. Manuel yรถntemlerle geliลŸtirme yaptฤฑฤŸฤฑmฤฑz en hataya aรงฤฑk kฤฑsฤฑm da burasฤฑ olmuลŸ oluyordu.

Artฤฑk LiveData data deฤŸiลŸtiฤŸinde bizi trigger ettiฤŸi iรงin, aลŸaฤŸฤฑdaki gibi bir yapฤฑ kurabiliriz. Bรถylece bir deฤŸiลŸiklik olduฤŸunda LiveData haber verecek ve biz de UI’ฤฑ update edebileceฤŸiz.

Data deฤŸiลŸtikรงe ui’ฤฑn nasฤฑl update edileceฤŸinden konuลŸtuk ama datayฤฑ nasฤฑl nerede รงekeceฤŸimizi konuลŸmadฤฑk. Bunu ViewModel iรงerisinde yapmak da bir รงรถzรผm olabilir ancak o zaman baลŸka ViewModel’lerde aynฤฑ data gerektiฤŸinde aynฤฑ kodu replike etmemiz gerekir ayrฤฑca birden fazla responsibility’nin aynฤฑ yerde implement edilmesine neden olur ki bu da seperation of concerns‘e uygun olmaz. Bu yรผzden datanฤฑn รงekilmesinden sorulu farklฤฑ bir class sรถz konusu olmaya baลŸlฤฑyor.

AลŸaฤŸฤฑdaki รถrnek retrofit kullanฤฑldฤฑฤŸฤฑ varsayฤฑlarak yazฤฑlmฤฑลŸ.

Bu iลŸlerden ise sorumlu olarak Repository modรผlleri atanabilir. Aslฤฑnda buna Repository yerine farklฤฑ bir isim de verilebilir ancak developer.android’in verdiฤŸi isimlendirmeye baฤŸlฤฑ kalmak bizi diฤŸer developerlarla ortak bir dil konuลŸmamฤฑzฤฑ saฤŸlar.

UserRepository ve ViewModel’i nasฤฑl baฤŸlayacaฤŸฤฑmฤฑz ise aลŸaฤŸฤฑdaki gibidir.

ลžu ana kadar konuลŸmadฤฑฤŸฤฑmฤฑz konulardan biri de cache. Her app’in cache ihtiyacฤฑ bulunmamakla hatta bazฤฑlarฤฑn cacheleme yapmama zorunluluฤŸu olmasฤฑyla birlikte ihtiyaรง durumunda bu da Repository’nin sorumluluฤŸunda olmalฤฑdฤฑr. EฤŸer cache de data varsa bunu dรถndรผrรผp yoksa yeni datayฤฑ รงekebilir.

KonuลŸmadฤฑฤŸฤฑmฤฑz bir diฤŸer konu da data’nฤฑn sรผrekliliฤŸi. ย Uygulama var olduฤŸu sรผrece burada cache iลŸimizi gรถrebilir. Ancak kullanฤฑcฤฑyฤฑ uygulama saatlerce bฤฑrakฤฑr ve Android sistemi de uygulamayฤฑ kill ederse iลŸler deฤŸiลŸir. Yukarฤฑdaki implementasyon bu case’de datanฤฑn tekrar รงekilmesini saฤŸlar. app’inizin yapฤฑsฤฑ gereฤŸi buna ihtiyacฤฑnฤฑz olacaฤŸฤฑ gibi, ihtiyacฤฑnฤฑz yoksa bu hem kullanฤฑcฤฑ iรงin kรถtรผ bir deneyim de gereksiz mobil data kullanฤฑmฤฑ olacaktฤฑr. Yine architecture componentlerle beraber hayatฤฑmฤฑza giren Room da bu soruna cevap iรงin geliลŸtirilmiลŸ durumda. Room’un รงรถzรผmรผ SQLite ORM ya da Realm ฤฑn sunduฤŸunda benzer bir รงรถzรผm aslฤฑnda. Ancak bu yazฤฑda Room’a รงok fazla girmek istemiyorum. ร–zetle local storage yapฤฑyor olarak dรผลŸรผnebiliriz.

Umarฤฑm architecture components’in neden รงฤฑktฤฑฤŸฤฑ ve nasฤฑl kullanฤฑlacaฤŸฤฑ hakkฤฑnda genel bir bakฤฑลŸ aรงฤฑsฤฑ yaratabilmiลŸimdir. Daha detaylฤฑ yazฤฑlar da paylaลŸmaya รงalฤฑลŸacaฤŸฤฑm. ๐Ÿ™‚

Referanslar:

3 responses to “Android Lifecycle-Aware components”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.