Android Jetpack架構(gòu)組件Lifecycle詳解
前言
Lifecycle是Jetpack架構(gòu)組件中用來(lái)感知生命周期的組件,使用Lifecycles可以幫助我們寫(xiě)出和生命周期相關(guān)更簡(jiǎn)潔更易維護(hù)的代碼。
生命周期
生命周期這個(gè)簡(jiǎn)單而又重要的知識(shí)相信大家早已耳熟能詳。假設(shè)我們現(xiàn)在有這樣一個(gè)簡(jiǎn)單需求:
這個(gè)需求只是一個(gè)實(shí)例,在真實(shí)的開(kāi)發(fā)中當(dāng)然不可能有這樣的需要:
在Activity 可見(jiàn)的時(shí)候,我們?nèi)プ鲆粋€(gè)計(jì)數(shù)功能,每隔一秒 將計(jì)數(shù)加1 ,當(dāng)Activity不可見(jiàn)的時(shí)候停止計(jì)數(shù),當(dāng)Activity被銷(xiāo)毀的時(shí)候 將計(jì)數(shù)置為0
OK,So easy~ ,新建Main3Activity 編寫(xiě)代碼如下所示:
public class Main3Activity extends AppCompatActivity { private static final String TAG = "Main3Activity"; int count = 0; /** * 是否計(jì)數(shù) */ private boolean whetherToCount = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); } @Override protected void onResume() { super.onResume(); whetherToCount = true; new Thread(new Runnable() { @Override public void run() { while (whetherToCount) { try { Thread.sleep(1000); count++; Log.d(TAG, "onResume: " + count); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } @Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop: ----"); whetherToCount = false; } @Override protected void onDestroy() { super.onDestroy(); whetherToCount = false; count = 0; } }
運(yùn)行結(jié)果如下所示:
符合我們的預(yù)期,你可能鄙視的看了我一眼,這樣多臃腫啊,我可是學(xué)過(guò)面向?qū)ο蟮娜?,所以你把工作放在了一個(gè)名為WorkUtil的類(lèi)中
public class WorkUtil { private static final String TAG = "WorkUtil"; private boolean whetherToCount = true; private int count = 0; public void start() { new Thread(new Runnable() { @Override public void run() { while (whetherToCount) { try { Thread.sleep(1000); count++; Log.d(TAG, "start: " + count); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } public void onStop() { whetherToCount = false; } public void onDestory() { count = 0; } }
然后再activity中的生命周期中分別執(zhí)行對(duì)應(yīng)的方法,感覺(jué)美滋滋~
然而 ,這樣還是不夠解耦,如果方法過(guò)多的話(huà) ,會(huì)讓view中的代碼越來(lái)越臃腫,那么 還有更好的方案嗎?這就是今天所說(shuō)的Lifecycle。我們待會(huì)回過(guò)頭來(lái)再優(yōu)化上面的代碼。
使用Lifecycle管理生命周期
我們通過(guò)改寫(xiě)WorkUtil類(lèi)來(lái)講解如何使用Lifecycle,讓W(xué)orkUtil類(lèi)實(shí)現(xiàn)LifecycleObserver
我們通過(guò)OnLifecycleEvent注解來(lái)注明方法所執(zhí)行的生命周期,如下所示:
public class WorkUtil implements LifecycleObserver { private static final String TAG = "WorkUtil"; private boolean whetherToCount = true; private int count = 0; @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void start() { new Thread(new Runnable() { @Override public void run() { while (whetherToCount) { try { Thread.sleep(1000); count++; Log.d(TAG, "start: " + count); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { whetherToCount = false; } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestory() { count = 0; } }
在Activity中注冊(cè)即可:
getLifecycle().addObserver(new WorkUtil());
這樣是不是簡(jiǎn)潔多了呢,那么我們?yōu)槭裁纯梢栽贏ctivity中直接使用getLifecycle().addObserver(new WorkUtil());呢,其實(shí)使用的是LifecycleOwner.getLifecycle, LifecycleOwner是單一方法接口,表示類(lèi)具有 Lifecycle,而如果activity繼承自AppcompatActivity或Fragment繼承自androidx.fragment.app.Fragment他們本身就是一個(gè)LifecycleOwner的實(shí)例,這是AndroidX庫(kù)幫我們自動(dòng)完成的。
自定義LifecycleOwner
如果我們的Activity由于各種原因繼承的不是AppcompatActivity而是Activity呢
我們可以看到這個(gè)時(shí)候,就不能直接使用getLifecycle,而要自定義一個(gè)LifecycleOwner了,我們讓Activity繼承自L(fǎng)ifecycleOwner,
使用LifecycleRegistry定義如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); lifecycleRegistry = new LifecycleRegistry(this); getLifecycle().addObserver(new WorkUtil()); }
@NonNull @Override public Lifecycle getLifecycle() { return lifecycleRegistry; }
這樣我們就實(shí)現(xiàn)了自定義LifecycleOwner了,不過(guò)大多數(shù)時(shí)候我們還是不需要自定義的。
優(yōu)雅的檢測(cè)應(yīng)用程序前后臺(tái)狀態(tài)
很多業(yè)務(wù)中我們都需要監(jiān)聽(tīng)?wèi)?yīng)用前后臺(tái)的狀態(tài) ,比如在前臺(tái)的時(shí)候開(kāi)始緩存任務(wù),在后臺(tái)的時(shí)候停止緩存任務(wù),其實(shí)方法有很多,比如
使用我們上面所說(shuō)的方法,監(jiān)聽(tīng)BaseActivity,但是都不夠優(yōu)雅,如果我們想監(jiān)聽(tīng)所有Activty的生命周期就要使用ActivityLifecycleCallbacks,我們新建ForegroundCallbacks類(lèi)實(shí)現(xiàn)ActivityLifecycleCallbacks
public class ForegroundCallbacks implements Application.ActivityLifecycleCallbacks { private static final String TAG = "ForegroundCallbacks"; @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { Log.d(TAG, "onActivityCreated: " + activity.getComponentName()); } @Override public void onActivityStarted(@NonNull Activity activity) { Log.d(TAG, "onActivityStarted: "+ activity.getComponentName()); } @Override public void onActivityResumed(@NonNull Activity activity) { Log.d(TAG, "onActivityResumed: "+ activity.getComponentName()); } @Override public void onActivityPaused(@NonNull Activity activity) { Log.d(TAG, "onActivityPaused: "+ activity.getComponentName()); } @Override public void onActivityStopped(@NonNull Activity activity) { Log.d(TAG, "onActivityStopped: "+ activity.getComponentName()); } @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) { Log.d(TAG, "onActivitySaveInstanceState: "+ activity.getComponentName()); } @Override public void onActivityDestroyed(@NonNull Activity activity) { Log.d(TAG, "onActivityDestroyed: "+ activity.getComponentName()); } }
添加一個(gè)初始化的方法:
/** * 初始化foregroundCallbacks * * @param appApplication application */ public static ForegroundCallbacks init(AppApplication appApplication) { instance = new ForegroundCallbacks(); appApplication.registerActivityLifecycleCallbacks(instance); return instance; }
在Application中進(jìn)行注冊(cè):
ForegroundCallbacks.init(this);
運(yùn)行項(xiàng)目日志如下:
現(xiàn)在我們知道肯定要在onActivityResumed和onActivityPaused兩個(gè)方法中進(jìn)行判斷,但是肯定不是說(shuō)進(jìn)入到了resumed就是在前臺(tái),進(jìn)入到了paused就是后臺(tái),因?yàn)槲覀兊膽?yīng)用會(huì)有多個(gè)activity,只有第一個(gè)activity在前臺(tái)的時(shí)候我們才提示在前臺(tái),只有所有activity都不可見(jiàn)的時(shí)候才提示在后臺(tái),按照這種思路我們編寫(xiě)對(duì)應(yīng)的處理
首先定義個(gè)接口 里面回調(diào)在前臺(tái)或在后臺(tái)的方法
public interface Listener { /** * 在前臺(tái) */ public void onBecameForeground(); /** * 在后臺(tái) */ public void onBecameBackground(); }
定義標(biāo)記位
private Runnable runnable; /** * 是否執(zhí)行過(guò)onResumed */ private boolean onResumed = false; /** * 是否執(zhí)行過(guò)onPaused */ private boolean onPaused = true;
@Override public void onActivityResumed(@NonNull Activity activity) { Log.d(TAG, "onActivityResumed: " + activity.getComponentName()); onPaused = false; if (runnable != null){ handler.removeCallbacks(runnable); } handler.postDelayed(runnable = new Runnable() { @Override public void run() { if (!onResumed) { listener.onBecameForeground(); onResumed = true; } } },600); } @Override public void onActivityPaused(@NonNull Activity activity) { Log.d(TAG, "onActivityPaused: " + activity.getComponentName()); onPaused = true; if (runnable != null){ handler.removeCallbacks(runnable); } handler.postDelayed(runnable = new Runnable() { @Override public void run() { if (onResumed && onPaused) { onResumed = false; listener.onBecameBackground(); } } }, 600); }
在這里我們進(jìn)行延遲0.6s的原因是為了避免啟動(dòng)新的activity 舊的activity頁(yè)面不可見(jiàn)時(shí)誤以為在后臺(tái),不過(guò)在真實(shí)的業(yè)務(wù)場(chǎng)景中還是需要按照細(xì)節(jié)進(jìn)行優(yōu)化,在applicaton添加事件回調(diào)
ForegroundCallbacks.init(this).addListener(new ForegroundCallbacks.Listener() { @Override public void onBecameForeground() { Log.d(TAG, "onBecameForeground: 在前臺(tái)"); } @Override public void onBecameBackground() { Log.d(TAG, "onBecameBackground: 在后臺(tái)"); } });
運(yùn)行程序切換到后臺(tái) 再切換回來(lái) 結(jié)果如下所示:
如此 我們就可以?xún)?yōu)雅的監(jiān)聽(tīng)?wèi)?yīng)用前后臺(tái)切換了。
是否感受到Lifecycle的強(qiáng)大了呢?
到此這篇關(guān)于Android Jetpack架構(gòu)組件Lifecycle詳解的文章就介紹到這了,更多相關(guān)Android Jetpack架構(gòu)組件Lifecycle內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android Jetpack架構(gòu)組件 ViewModel詳解
- Android 生命周期架構(gòu)組件使用方法
- Android架構(gòu)組件Room的使用詳解
- Android架構(gòu)組件Room指南
- Android-ViewModel和LiveData使用詳解
- Android LiveData使用需要注意的地方
- Android mvvm之LiveData原理案例詳解
- Android 基于MediatorLiveData實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理
- 詳解Android JetPack之LiveData的工作原理
- Android架構(gòu)組件LiveData使用詳解
相關(guān)文章
探秘Android手勢(shì)事件機(jī)制與優(yōu)化技巧
在Android開(kāi)發(fā)中,手勢(shì)操作被廣泛應(yīng)用于各種應(yīng)用場(chǎng)景,如滑動(dòng)、雙擊等。本文將介紹Android手勢(shì)事件傳遞的原理,包括手勢(shì)事件的類(lèi)型、分發(fā)機(jī)制和處理流程等內(nèi)容,并提供一些優(yōu)化用戶(hù)體驗(yàn)的技巧,需要的朋友可以參考下2023-06-06仿墨跡天氣在Android App中實(shí)現(xiàn)自定義zip皮膚更換
這篇文章主要介紹了仿墨跡天氣在Android App中實(shí)現(xiàn)自定義zip皮膚更換的方法,即讓用戶(hù)可以自行通過(guò)自制或者下載的zip皮膚包進(jìn)行換膚,需要的朋友可以參考下2016-02-02淺談Android獲取ImageView上的圖片,和一個(gè)有可能遇到的問(wèn)題
下面小編就為大家?guī)?lái)一篇淺談Android獲取ImageView上的圖片,和一個(gè)有可能遇到的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04淺談Android Service服務(wù)的高級(jí)技巧
這篇文章主要介紹了淺談Android 服務(wù)的高級(jí)技巧,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07Android設(shè)計(jì)模式之Builder模式詳解
這篇文章主要為大家詳細(xì)介紹了Android設(shè)計(jì)模式之Builder模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Android同時(shí)安裝Release和Debug版本的方法
這篇文章主要介紹了Android同時(shí)安裝Release和Debug版本的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12僅5步搞定Android開(kāi)發(fā)環(huán)境部署 Android開(kāi)發(fā)環(huán)境搭建教程
僅5步搞定Android開(kāi)發(fā)環(huán)境部署,這篇文章主要為大家詳細(xì)介紹了Android開(kāi)發(fā)環(huán)境搭建教程,感興趣的小伙伴們可以參考一下2016-02-02Android PopWindow 設(shè)置背景亮度的實(shí)例
這篇文章主要介紹了Android PopWindow 設(shè)置背景亮度的實(shí)例的相關(guān)資料,這里提供實(shí)現(xiàn)方法,希望能幫助有所需要的朋友,需要的朋友可以參考下2017-08-08