这节主要介绍Activity生命周期相关常识
我所了解的Activity生命周期
android设计者把Activity设计的有生命周期,就犹如它类似于生物相同要阅历生老病死,是的Activity也的确如此,比方用户翻开一个Activity代表它创立了,当用户按回来按键的时分代表这Activity毁掉死掉了。
在Activity从生到死的生命周期内,它要阅历许多的状况,比方当时显现的Activity被其他的Activity遮挡住了,被遮挡的Activity是有一个状况的;又比方当时显现的Activity被一个对话框遮挡住了一半的时分它的状况又是啥。
Activity不同的状况也是在告知Activity需求针对不同的状况做不同的作业了,比方Activity毁掉的时分需求把要害的资源毁掉掉等。
那Activity的状况,是由谁发出的,又是经过什么方式告诉Activity的呢?
Activiity状况发出者是体系(更具体的说是体系进程中的ActivityManagerService(简称AMS)服务),AMS办理着一切的Activity,Activity的状况需求它来告诉,它来统一和谐。
经过调用Activity的不同的回调办法来把状况告诉到Activiity,调用回调办法进行告诉这是最靠谱最准确的方式,不论什么样的状况AMS都会即时告诉到对应Activity。在完成调用回调办法的时分用到了面向对象的两个特性:继承和多态,多态:假设子类重写了父类的办法,在运转的时分会调用子类中的重写的办法,而不会调用父类的被重写办法。
Activity的生命周期
现在就来看下Activity的生命周期内不同的状况和对应的回调办法以及不同状况之间的切换,回调办法都是以on最初的(如onCreate)。
先来看下官方的一张图
1. create状况
create状况代表体系会告诉Activity处于开端创立的状况,它对应的回调办法是 onCreate 此办法在Activity生命周期内只调用一次,此办法需求调用setContentView办法来设置Activity对应的view只有设置view会才会在屏幕上显现,否则便是一个空白的界面。由于这办法被调用一次,还能够在这办法中初始化一些特点,view等
2. start状况
onCreate办法退出后,进入start状况,代表体系告诉Activity进入”已发动状况“对于用户可见,可是不能与用户进行交互,它对应的回调办法是 onStart 此办法很简略
3. resume状况
onStart办法退出后,进入resume状况,代表体系Activity的界面现已显现而且用户的输入事件都交给当时Activity的对应view处理,Activity处于整个Activity仓库的最前面。它对应的回调办法是 onResume onResume办法履行结束后,Activity就处于运转状况。
4. pause状况
当时Activity被其他Activity或dialog遮挡,或许用户点击了回来键,体系都会告诉Activity进入pause状况,进入该状况代表Activity仍是可见的,可是不能与用户进行交互。它下个进入的状况是stop或许resume状况。它对应的回调办法是 onPause onPause办法履行特别快,不要在这个办法中保存数据或许恳求网络,否则会影响app的运转(如是发动一个Activity导致进入该状况,则会影响下个Activity的发动,否则会影响当时Activity的毁掉)
5. stop状况
当时的Activity被其他全屏及非通明的Activity遮挡,或许用户点击了回来键,体系都会告诉Activity进入stop状况,进入该状况就代表该Activity彻底不行见了。它下个进入的状况是destory或许start状况(如是用户点击回来键导致的则进入destory,否则当Activity从头显现康复的时分进入start状况),它对应的回调办法是 onStop 该办法做的作业是比方暂停或许封闭乃至毁掉一些资源,比方播映视频Activity,进入该界面后就需求把视频暂停掉,而且开释占用的与声响相关的资源。假设Activity没有毁掉,当Activity再次进入onResume办法的时分,需求在该办法中把视频继续播映,而且申请与声响有关的资源。
6. restart状况
Activity并非由毁掉状况而进入stop状况的,当Activity再次回到前台(被用户看到),就会先进入restart状况,随后onStart,onResume办法被顺次调用确保Activity进入resume状况,它所对应的回调办法是 onRestart
7. destory状况
代表Activity进入毁掉状况,它对应的回调办法是 onDestory 此办法是Activity生命周期终究一个履行的回调办法,在此办法中履行Activity所占据的资源的毁掉作业。
小结
Activity的生命周期内涵收到体系告诉的对应状况时分,就需求依据对应的状况做出不同的作业,在onPause办法中不能进行网络恳求等操作,在onStop办法中需求停掉一些与界面无关系的资源,这办法更不能进行网络恳求的操作,在onDestory办法中开释Activity所占有的资源(这样才不至于呈现内存走漏等导致app crash等状况)。以上的操作能够让app做到尽可能少的耗费流量,尽可能少的耗费电量,做到更好的用户体会。这样app被用户卸载的几率就降低许多。
引起Activity生命周期改变的状况
引起Activity生命周期改变主要有下面几种:
装备发生了更改 装备包括的内容许多:比方手机反正屏切换,在设置中语言的切换,体系文字大小切换,输入法切换,当时运用的权限发生改变等。
装备发生了改变后,体系会告诉Activity的生命周期从onCreate到onResume从头履行(我们有爱好能够实验下,在自己重写的Activity的生命周期办法中运用Log日志东西加上日志,更改以上说到的装备,看Activity的回调办法是否履行了)
当然了针对装备发生改变不单单会引起Activity从头履行生命周期流程,还有个比较不好的影响:会影响用户体会。拿反正屏切换来举例子:当手机由竖屏切换为横屏后,会看到当时的界面和竖屏的时分界面状况不一致了(比方竖屏时分当时界面很长超出了一屏,这时分停留在50%的进展位置,当横屏后界面停留在了0%的位置),这其实十分影响用户体会。
当然针对装备引起Activity状况改变的状况,体系也答应有其他一种选择,便是能够不对某些装备做呼应,在AndroidManifest清单文件中对Activity装备时分增加对应的装备:android:configChanges=”keyboardHidden|screenSize|orientation” , orientation是当反正屏切换时分,当时Activity不呼应状况改变。
当然还有其他一种选择便是保存康复界面状况机制,对应Activity的回调办法onSaveInstanceState和onRestoreInstanceState,在这就不具体介绍了。
发动了一个全屏非通明的Activiity 这儿强调全屏非通明的Activity意味着和非全屏或许通明乃至半通明Activity,会影响被遮挡Activity进入不同的生命周期状况。
发动全屏非通明的Activity,体系会告诉被遮挡Activity的onPause, onStop办法顺次被调用。
发动非全屏或许通明半通明Activity或许显现一个Dialog 这种状况下,基层的Activity会仍然显现,这时分体系会告诉它的onPause办法会被履行。
用户点击回来按钮 这种状况,代表用户不需求当时Activity了能够毁掉了。体系会告诉Activity的onPause, onStop, onDestory办法顺次履行,而且Activity会从体系内存中移除。
低内存导致Activity进程被杀 在处于低内存的状况下,为了开释更多的内存,需求把一些处于后台的进程杀掉。在这种状况下需求运用保存康复界面状况机制,以便在Activity从头树立后,从保存的界面状况中进行康复。
Activity状况和进程状况及进程被中止
下面是官方的关于 Activity状况和进程状况及进程被中止 的一张图
对上面几个概念进行解说: 前台进程:指的是app中有一个Activity处于或许行将处于resume状况。 后台失掉焦点的进程:指的是app中有一个Activity处于pause状况。 后台不行见进程:指app中一切的Activity都处于stop状况,这种状况进程就为不行见后台进程。
随着手机上翻开的app越来越多,体系的内存越来越严重,随之带来整个手机越来越卡。体系就需求开释尽量多的内存,在开释内存的时分,体系会依据上面的图,来顺次开释内存。
后台不行见的进程自然成为最有可能被中止的方针(app都退居后台了,留着这样的进程干啥),当然了这说的常识可能性最大,进程本来就有优先级一说,优先级低的被中止的可能性要高于优先级高的。而且进程还有体系进程和普通进程一说,普通进程肯定会先被中止掉。
后台失掉焦点进程被中止的可能性较大,毕竟这种进程的Activity仍是能够被用户看到的,仅仅失掉焦点了而已。
运用lifecycle组件来感知生命周期状况的改变
lifecycle组件的作用是啥?只有弄清了它的作用才会加深对它的了解,万事万物不行能凭白无故的发生,它可定是处理了从前存在的问题。那我们来看下现在的Activity生命周期回调办法里边存在啥问题? 比方一个Activity中包括了定位功用,播映视频功用,运用相机功用。来看段它的代码(下面都是伪代码 为了阐明问题,当然一般一个Activity中是不会呈现camera,location,video同时都用到的状况,仅仅为了阐明问题)
public class MainActivity extends Activity{
//定位功用的类
private Location mLocation;
//camera 这都是伪代码
private Camera mCamera;
//播映视频的类
private Video mVideo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//对location,camera,video 进行初始化
}
@Override
protected void onResume() {
super.onResume();
//由于进入resume状况,因而把相应的模块翻开,假设它们都有start办法
mCamera.start();
mLocation.start();
mVideo.start();
}
@Override
protected void onStop() {
super.onStop();
//由于进入stop状况,因而把相应的模块stop,假设它们都有stop办法
mCamera.stop();
mLocation.stop();
mVideo.stop();
}
@Override
protected void onDestroy() {
super.onDestroy();
//由于进入destory状况,因而把相应的模块开释掉,假设它们都有destory办法
mCamera.destory();
mLocation.destory();
mVideo.destory();
}
}
上面代码中依据Activity不同的生命状况会对camera,video,location模块进行不同的处理,比方当时进入stop状况,那就十分有必要把它们都中止掉,不停掉就会有问题(比方video不停掉,就会发现界面现已看不到了,可是还有声响,而且还一向耗费着手机的电量和流量,这彻底不是一个好的用户体会的app),比方在进入destory状况,需求三个模块把占用的资源毁掉掉。
上面的Activity的代码还比较简略,可是当事务越来越多的时分,不同的生命周期回调办法里边会充满着更多的代码,这就会为以后代码维护,复用等带来极高的本钱。就比方camera,video,location模块中的某个模块需求在其他Activity中运用,那是不是需求在这个Activity的对应生命周期回调办法里边对模块进行处理,这根本就没有达到模块复用的作用。
形成以上问题的原因便是由于 只能在Activity的生命周期回调办法里边才干知道状况的改变,那只能把与状况有关的代码写在Activity的回调办法里边,终究导致代码越来越多。那官方给出了lifecycle组件来处理此问题,处理此问题的核心便是回调,大约原理是:只要把监听生命周期改变的回调传递给它,它就能把关心的状况告诉到你。
lifecycle组件 该组件是Android Jetpack的一部分,坐落androidx.lifecycle包下。主要的几个要害类和接口:Lifecycle,DefaultLifecycleObserver,LifecycleOwner,LifecycleRegistry,LifecycleEventObserver
lifecycle的运用十分简略,主要分为:
- 完成DefaultLifecycleObserver或许LifecycleEventObserver 这俩接口中的恣意一个
- 编写的Activity需求继承FragmentActivity或许它的子类,调用它的addObserver办法把第一步的实例作为参数
下面来看下例子,对上面MainActivity的改造
public class MainActivity extends FragmentActivity {
private Camera myCamera = new Camera(this);
private Video myVideo = new Video(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
public class Video {
private Context mContext;
private MyLifecycleObserver myLifecycleObserver = new MyLifecycleObserver();
private class MyLifecycleObserver implements LifecycleEventObserver {
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_CREATE) {
//初始化办法
init();
} else if (event == Lifecycle.Event.ON_DESTROY) {
destory();
} else if (event == Lifecycle.Event.ON_RESUME) {
start();
} else if (event == Lifecycle.Event.ON_STOP) {
stop();
}
}
}
public Video(Context context) {
mContext = context;
if (mContext instanceof LifecycleOwner) {
((LifecycleOwner)mContext).getLifecycle().addObserver(myLifecycleObserver);
}
}
}
public class Camera {
private Context mContext;
private MyLifecycleObserver myLifecycleObserver = new MyLifecycleObserver();
private class MyLifecycleObserver implements DefaultLifecycleObserver {
private final String TAG = "MyCamera$LifecycleObserver";
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
init();
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
destory();
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
start();
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
stop();
}
}
public Camera(Context context) {
mContext = context;
if (mContext instanceof LifecycleOwner) {
((LifecycleOwner)mContext).getLifecycle().addObserver(myLifecycleObserver);
}
}
}
Location和上面的代码基本一致,就不写了。
看了上面的代码,有没有感觉MainActivity清爽多了,Camera,Video,Location在自己类中就能够收到Activity生命周期的改变,这样它们便是高内聚低耦合,可复用的模块了。
有了lifecycle这个组件后,许多的库都运用上了,比方Glide库,在加载图片时分,若Activity进入stop状况,应该中止恳求网络,是不是在Activity的onStop办法里边没有看到它的身影,那是由于它现已在自己模块内处理了,把细节隐藏在自己模块内。还有LiveData,ViewModel等Jetpack的库都用了这个组件。
总结
这节介绍了Activity的生命周期及Activity不同的状况和状况对应的回调办法,以及不同状况的切换。而且介绍了影响Activity状况改变的状况。还介绍了前台进程,失掉焦点的后台进程和不行见后台进程,以及它们与被体系中止的可能性。终究介绍了lifecycle组件,强烈建议我们运用这个组件,不要在Activity里边写过多的逻辑(能作为一个模块独立出来就尽量独立出来)。