Android Fundamentals-1 | The Activity Lifecycle

Suveybesena
8 min readApr 28, 2022

--

Merhabalar,

Bu seride doküman okuma alışkanlığımı geliştirmek ve Android temellerine dair daha kapsamlı bilgi edinmek adına developer.android.com üzerinden seçtiğim konular hakkında notlarımı paylaşıyor olacağım. Keyifli okumalar.

The Activity Lifecycle

Bir kullanıcı uygulamamızda gezinirken, uygulamamızdan çıkarken ve uygulamaya geri dönerken, uygulamamızdaki Activity örnekleri yaşam döngülerindeki farklı durumlar arasında geçiş yapar. Activity sınıfı, activity’nin bir durumun değiştiğini bilmesini sağlayan bir dizi callback sağlar: sistemin bir aktivite oluşturduğunu, durdurduğunu veya devam ettirdiğini veya içinde bulunduğu süreci yok ettiğini belirtir.

Lifecycle callback yöntemlerinde, kullanıcı aktiviteden ayrılıp tekrar girdiğinde aktiviten nasıl davranacağını bildirebiliriz. Örneğin, bir kullanıcının video izlediği bir ekranda, kullanıcı başka bir uygulamaya geçerse videoyu duraklatabilir ve ağ bağlantısını sonlandırabiliriz. Kullanıcı geri döndüğünde, ağa yeniden bağlanabilir ve kullanıcının videoyu aynı noktadan devam ettirmesine izin verebiliriz. Başka bir deyişle, her callback, belirli bir durum değişikliğine uygun olan belirli işleri gerçekleştirmemize izin verir. Doğru zamanda doğru işi yapmak ve geçişleri düzgün bir şekilde ele almak, uygulamayı daha sağlam ve performanslı hale getirir. Örneğin Lifecycle callbacklerinin iyi bir şekilde uygulanmasının bize sağlayacağı faydaları şöyle sıralayabiliriz:

· Kullanıcı, uygulamanızı kullanırken bir telefon görüşmesi alırsa ya da başka bir uygulamaya geçerse uygulamanın crash olmasını engelleyebilirsiniz.

· Kullanıcının aktif olarak kullanmadığı değerli sistem kaynaklarından tasarruf edebilirsiniz.

· Uygulamanızdan ayrılıp geri dönen kullancının ilerlemesini kaybetmeden devam ettirebilirsiniz.

· Uygulama rotate edildiğinde kullanıcının bilgilerini tutmaya devam edebilirsiniz.

Activity Lifecycle kavramları

Activity yaşam döngüsünün aşamaları arasındaki geçişlerde gezinmek için Activity sınıfı altı temel callback seti sağlar: onCreate(), onStart(), onResume(), onPause(), onStop() ve onDestroy(). Bir aktivite yeni bir duruma girerken sistem bu callbacklarden her birini çağırır.

Kullanıcı aktiviteden ayrılmak için işlem yaptığında, sistem aktiviteyi kaldırmak için metotları çağırır. Bazı durumlarda, activity hala bellekte kalır (örneğin, kullanıcı başka bir uygulamaya geçtiğinde) ve yine de ön plana geri dönebilir. Kullanıcı o aktiviteye dönerse aktivite kullanıcının kaldığı yerden devam eder.

Faaliyetimizin karmaşıklığına bağlı olarak, tüm yaşam döngüsü yöntemlerini uygulamamız gerekmeyebilir. Ancak, her birini anlamamız ve uygulamamızın kullanıcı deneyimi için kullanıcıların beklediği şekilde davranmasını sağlayan callBack methodlarını uygulamamız önemlidir.

Lifecycle Callbackler

setContentView() öğesini çağırmak gibi bazı eylemler, activity yaşam döngüsü yöntemlerinin kendilerine aittir. Ancak, bağımlı bir bileşenin eylemlerini uygulayan kod, bileşenin kendisine yerleştirilmelidir. Bunun için bağımlı bileşenin lifecycle aware olması gerekir.

Bu callBack, sistem activity’i ilk oluşturduğunda tetiklenir. onCreate() yönteminde, etkinliğin tüm ömrü boyunca yalnızca bir kez gerçekleşmesi gereken temel uygulama başlatma mantığını gerçekleştiririz. Örneğin, onCreate() methodunda verileri listelere bağlayabilir, activity’i bir ViewModel ile ilişkilendirebilir veya o sınıf kapsamında kullanacağımız bazı değişkenleri tanımlayabiliriz. Ayrıca onCreate’de activity’nin önceden kaydedilmiş durumunu içeren bir Bundle nesnesi olan saveInstanceState parametresini alır. Aktivite daha önce hiç var olmamışsa, Bundle nesnesinin değeri null olur.

Aktivitemizin yaşam döngüsüne bağlı, “lifecycle aware” bir componentimiz varsa, ON_CREATE eventini alacaktır. @OnLifecycleEvent annotasyonu ekleyerek bu methodu çağırırız, böylece lifecycle aware componentimiz, oluşturulan durum için ihtiyaç duyduğu herhangi bir kurulum kodunu gerçekleştirebilir.

onCreate() yöntemi yürütmeyi bitirdikten sonra, Activity Started durumuna girer ve sistem, hızlı bir şekilde art arda onStart() ve onResume() yöntemlerini çağırır.

Activity Started durumuna girdiğinde, sistem bu callback’i başlatır. onStart() çağrısı, uygulamayı aktivitenin ön plana girmesi ve etkileşimli hale gelmesi için hazırlanırken, aktiviteyi kullanıcıya görünür hale getirir. Bu yöntem, uygulamanın kullanıcı arabirimini içeren kodu initialize ettiği yerdir.

Activity Started duruma geçtiğinde, aktivitenin yaşam döngüsüne bağlı lifecycle aware herhangi bir component ON_START eventini alır.

onStart() yöntemi çok hızlı bir şekilde tamamlanır ve Created durumunda olduğu gibi, activity Started durumunda yerleşik kalmaz. Bu callback bittiğinde, activity Resumed durumuna girer ve sistem onResume() yöntemini çağırır.

Activity Resumed durumuna girdiğinde ön plana gelir ve ardından sistem onResume() callBackini başlatır. Bu, uygulamamızın kullanıcıyla etkileşime girdiği durumdur. Uygulama, odağı uygulamadan uzaklaştıracak bir şey olana kadar bu durumda kalır. Örneğin bir telefon araması alınması, kullanıcının başka bir etkinliğe gitmesi veya cihaz ekranının kapanması olabilir.

Aktivite Resumed duruma geçtiğinde, activity’nin yaşam döngüsüne bağlı lifecycle aware herhangi bir bileşen ON_RESUME eventini alır. Bu, lifecycle aware bileşenlerinin, bileşen görünürken ve ön plandayken çalışması gereken herhangi bir işlevi, örneğin bir kamera önizlemesini başlatmak gibi etkinleştirebildiği yerdir.

Uygulama arka plana alındığında ya da resume durumunu bölen bir olay meydana geldiğinde, Activity Paused durumuna girer ve sistem onPause() callbackini başlatır.

Activity, Paused durumundan Resumed durumuna dönerse, sistem bir kez daha onResume() yöntemini çağırır. Bu nedenle, onPause() sırasında serbest bıraktığımız bileşenleri başlatmak için onResume()’u uygulamamız ve aktivitenin Resumed durumuna her girdiğinde gerçekleşmesi gereken diğer initialize işlemlerini gerçekleştirmemiz gerekir.

Bileşen ON_RESUME eventini aldığında kameraya erişen lifecycle aware bir bileşen örneği aşağıda verilmiştir:

LifecycleObserver ON_RESUME eventini aldığında yukarıdaki kod kamerayı başlatır. Bununla birlikte, çoklu pencere modunda, activity Paused durumundayken bile tamamen görünebilir. Örneğin, kullanıcı çoklu pencere modundayken activityi içermeyen diğer pencereye dokunduğunda aktivitemiz Paused durumuna geçer. Kameranın yalnızca uygulama Resume ettiğinde (ön planda görünür ve etkin olduğunda) etkin olmasını istiyorsak, yukarıda gösterilen ON_RESUME olayından sonra kamerayı başlatabiliriz. Activity Paused ancak görünür durumdayken (örneğin çoklu pencere modunda) kamerayı aktif tutmak istiyorsak, bunun yerine kamerayı ON_START olayından sonra başlatmamız gerekir. Ancak, activity Paused edildiğinde kamerayı etkinleştirmenin, çoklu pencere modunda başka Resumed uygulamaya kameraya erişimi engelleyebileceğini unutmamamız gerekir. Bazen aktivite Paused edildiğinde kamerayı etkin tutmak gerekebilir, ancak bu kullanıcı deneyimini bozabilir. Çoklu pencere bağlamında paylaşılan sistem kaynaklarının kontrolünü ele almanın yaşam döngüsünün neresinde daha uygun olduğunun düşünülmesi gerekir.

Hangi eventte olayında bir initialize işlemi gerçekleştirmeyi seçersek seçelim, sonlandırmak için ilgili yaşam döngüsünü kullanmamız önemlidir. ON_START olayından sonra bir şey başlatırsak, ON_STOP olayından sonra sonlandırmalı, ON_RESUME olayından sonra başlatırsanız, ON_PAUSE olayından sonra sonlandırmalıyız.

Yukarıdaki kod parçacığının, kamera başlatma kodunu lifecycle aware bir componente yerleştirdiğini unutmamalıyız. Bunun yerine bu kodu doğrudan onStart() ve onStop() gibi aktivite lifecycle callBacklerine koyabilirsiniz, ancak bu önerilmez. Bu mantığı bağımsız, yaşam döngüsüne duyarlı bir bileşene eklemek, kodu çoğaltmak zorunda kalmadan bileşeni birden çok etkinlikte yeniden kullanmanıza olanak tanır.

Sistem, kullanıcının aktivitemizden ayrıldığının ilk göstergesi olarak bu yöntemi çağırır (ancak bu her zaman aktivitenin yok edildiği anlamına gelmez); etkinliğin artık ön planda olmadığını gösterir (ancak kullanıcı çoklu pencere modundaysa yine de görünebilir). Activity Paused durumundayken devam etmemesi (veya ölçülü olarak devam etmesi) gereken ve kısa süre içinde devam etmesini beklediğimiz işlemleri duraklatmak veya ayarlamak için onPause() yöntemini kullanırız. Bir etkinliğin bu duruma girmesinin birkaç nedeni vardır. Örneğin:

· onResume() bölümünde açıklandığı gibi, bazı olaylar uygulama yürütmesini kesintiye uğratır. Bu yaygın durumdur.

· Android 7.0 (API seviyesi 24) veya sonraki sürümlerde, birden çok uygulama çoklu pencere modunda çalışır. Herhangi bir zamanda uygulamalardan (pencerelerden) yalnızca biri odaklandığından, sistem diğer tüm uygulamaları duraklatır.

· Yarı açılma durumunda, (bir dialog kutusu gibi) Activity hala kısmen görünür ancak odakta olmadığı sürece duraklatılmış olarak kalır.

Activity Paused duruma geçtiğinde, aktivitemizin lifecycle aware herhangi bir bileşe0in ON_PAUSE eventini alır. Bu, lifecycle componentleri, kamera ön izlemesini durdurmak gibi, bileşen ön planda değilken çalıştırılması gerekmeyen herhangi bir işlevi durdurabileceği yerdir.

Ayrıca, activity duraklatıldığında ve kullanıcının bunlara ihtiyacı olmadığında sistem kaynaklarını, sensörleri (GPS gibi) veya pil ömrünü etkileyebilecek kaynakları serbest bırakmak için onPause() yöntemini de kullanabiliriz. Bununla birlikte, yukarıda onResume() bölümünde bahsedildiği gibi, Duraklatılan bir activity, çoklu pencere modundaysa yine de tamamen görünür olabilir. Bu nedenle, çoklu pencere modunu daha iyi desteklemek için UI ile ilgili kaynakları ve işlemleri tamamen serbest bırakmak veya ayarlamak için onPause() yerine onStop() kullanmayı düşünebiliriz.

ON_PAUSE eventine tepki veren aşağıdaki LifecycleObserver örneği, ON_RESUME eventi alındıktan sonra başlatılan kamerayı serbest bırakan yukarıdaki ON_RESUME olay örneğinin karşılığıdır:

onPause() yürütmesi çok kısadır ve kaydetme işlemlerini gerçekleştirmek için mutlaka yeterli zamanı sağlamaz. Bu nedenle, uygulama veya kullanıcı verilerini kaydetmek, ağ aramaları yapmak veya veritabanı işlemlerini yürütmek için onPause() kullanmamalıyız; bu tür çalışmalar, method tamamlanmadan tamamlanmayabilir. Bunun yerine, onStop() sırasında ağır yük kapatma (heavy-load shutdown operations) işlemlerini gerçekleştirmeliyiz.

onPause() yönteminin tamamlanması, aktivitenin Paused durumundan çıktığı anlamına gelmez. Bunun yerine, aktivite devam edene veya kullanıcı tarafından tamamen görünmez hale gelene kadar aktivite bu durumda kalır. Aktivite devam ederse, sistem bir kez daha onResume() geri çağrısını başlatır. Etkinlik Paused durumundan Resumed durumuna dönerse, sistem Activity örneğini bellekte yerleşik tutar ve sistem onResume()’yi çağırdığında bu örneği geri çağırır. Bu senaryoda, Resumed durumuna giden callBacklerin herhangi biri sırasında oluşturulan bileşenleri yeniden başlatmamız gerekmez. Aktivite tamamen görünmez hale gelirse, sistem onStop()’u çağırır.

Activity artık kullanıcı tarafından görülmediğinde, Stopped durumuna girmiştir ve sistem onStop() callBackini başlatır. Bu, örneğin yeni başlatılan bir acvitity tüm ekranı kapladığında ortaya çıkabilir. Sistem ayrıca aktivitenin çalışması bittiğinde ve sonlandırılmak üzereyken onStop()’u çağırabilir.

Activity stopped duruma geçtiğinde, activityinin yaşam lifecycle aware herhangi bir component ON_STOP eventini alır. Bu, lifecycle componentlerin, bileşen ekranda görünmezken çalışmasına gerek olmayan herhangi bir işlevi durdurabileceği yerdir.

onStop() yönteminde, uygulama, kullanıcı tarafından görülmezken ihtiyaç duyulmayan kaynakları serbest bırakmalı veya ayarlamalıdır. Örneğin, uygulamamız animasyonları duraklatabilir veya ayrıntılı konum güncellemelerinden kaba ayrıntılı konum güncellemelerine geçebilir. onPause() yerine onStop() kullanılması, kullanıcı aktivitemizi çoklu pencere modunda görüntülediğinde bile UI ile ilgili çalışmanın devam etmesini sağlar.

Göreceli olarak CPU yoğun kapatma işlemleri gerçekleştirmek için onStop()’u da kullanmamız gerekir. Örneğin, bilgileri bir veritabanına kaydetmek için daha uygun bir zaman bulamıyorsak, bunu onStop() sırasında yapabiliriz. Aşağıdaki örnek, taslak notun içeriğini kalıcı depolamaya kaydeden bir onStop() uygulamasını göstermektedir: Burada notun son taslağını kaydediyoruz, çünkü activity duruyor ve mevcut not ilerlemesinin kaybolmadığından emin olmak istiyoruz.

Etkinliğimiz Stopped durumuna girdiğinde, Activity nesnesi bellekte yerleşik olarak tutulur: Tüm durum ve üye bilgilerini tutar, ancak pencere yöneticisine (Window manager)bağlı değildir. Aktivite devam ettiğinde, aktivite bu bilgiyi hatırlatır. Resumed durumuna callBacklerin herhangi biri sırasında oluşturulan bileşenleri yeniden başlatmamız gerekmez. Sistem ayrıca düzendeki her View nesnesi için geçerli durumu da takip eder, böylece kullanıcı bir EditText pencere aracına metin girerse, bu içerik korunur, böylece onu kaydetmemiz ve geri yüklememiz gerekmez.

Stopped durumundan, activity ya kullanıcıyla etkileşime geçmek için geri gelir ya da çalışması biter ve gider. Aktivite geri gelirse, sistem onRestart()’ı çağırır. Aktivitenin çalışması biterse, sistem onDestroy()’u çağırır.

Activity yok edilmeden önce çağrılır. Sistem bu callBack’i şu nedenle başlatır:

· kullanıcının aktiviteyi tamamen kapatması veya aktivitede finish() çağrılması nedeniyle,

· Sistem, bir yapılandırma değişikliği (cihaz döndürme veya çoklu pencere modu gibi) nedeniyle etkinliği geçici olarak yok eder ise.

Activity Destroyed duruma geçtiğinde, aktivitenin yaşam döngüsüne bağlı, lifecycle aware herhangi bir bileşen ON_DESTROY eventini alacaktır. Bu, yaşam döngüsü bileşenlerinin Aktivite yok edilmeden önce ihtiyaç duyduğu her şeyi temizleyebildiği yerdir.

Neden yok edildiğini anlamak için Activity’e logic koymak yerine, aktivitemizin görünüm verilerini sağlayan bir ViewModel nesnesi kullanabiliriz. Aktivite bir konfigürasyon değişikliği nedeniyle yeniden oluşturulacaksa, ViewModel korunacağı ve bir sonraki Activity örneğine verileceği için hiçbir şey yapmasına gerek yoktur. Aktivite yeniden oluşturulmayacaksa, o zaman ViewModel, yok edilmeden önce ihtiyaç duyduğu tüm verileri temizleyebileceği onCleared() yöntemine sahip olacaktır.

Bu iki senaryoyu isFinishing() yöntemiyle ayırt edebiliriz.

Aktivite bitiyorsa, onDestroy(), aktivitenin aldığı son lifecycle callBack’idir. Bir yapılandırma değişikliğinin sonucu olarak onDestroy() çağrılırsa, sistem hemen yeni bir etkinlik örneği oluşturur ve ardından yeni yapılandırmada bu yeni örnek üzerinde onCreate() öğesini çağırır.onDestroy() callBack’i, onStop() gibi daha önceki geri aramalar tarafından henüz serbest bırakılmamış tüm kaynakları serbest bırakmalıdır.

Serinin devamı için;

Okuduğunuz için teşekkür ederim, bir sonraki yazıda görüşmek üzere :)

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

--

--