Android生命周期和启动模式

一、Activity生命周期

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(只在Activity1中设置6中方法显示)
当用户点击Activity1上的按钮启动Activity2(对话框),此时屏幕处于半遮蔽状态,此时Activty会调用onPause,而当点击返回时,Activity1重新恢复,此时调用onResume(获取焦点)

在这里插入图片描述

3、activity七个方法

onCreate():当Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次这个方法。通常用于初始化设置,为Activity设置所要使用的布局文件,为按钮绑定监听器等静态的设置操作。

onStart():当Activity可见未获得用户焦点不能交互时系统会调用。

onRestart():当Activity已经停止然后重新被启动时系统会调用。
如:当本页面被另一个页面完全覆盖后,又重新回到本页面,被激活此时就会调用onRestart

onResume():当Activity可见且获得用户焦点能交互时系统会调用。

onPause():用来存储持久数据。到这一步是可见但不可交互的,系统会停止动画等消耗CPU的事情。从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。

onStop():当Activity被新的Activity完全覆盖不可见时被系统调用。

onDestroy():当Activity(用户调用==finish()==或系统由于内存不足)被系统销毁杀掉时系统调用,(整个生命周期只调用1次)用来释放onCreate()方法中创建的资源,如结束线程等。

4、android三个嵌套循环

(1)Activity完整的生命周期:从第一次调用onCreate()开始直到调用onDestroy()结束。

(2)Activity的可视生命周期:从调用onStart()到相应的调用onStop()。在这两个方法之间,可以保持显示Activity所需要的资源。如在onStart()中注册一个广播接收者监听影响你的UI的改变,在onStop()中注销。

(3)Activity的前台生命周期:从调用onResume()到相应的调用onPause()。

问题1:ActivityA跳转ActivityB,再按下返回键,A,B的生命周期执行顺序是什么?
当A跳转B的时候,A先执行onPause,然后是B再执行onCreate,onStart,onResume,最后才执行A的onStop
当B按下返回键,B先执行onPause,然后A再执行onRestart,onStart,onResume。最后B执行onStop,onDestory

问题2:如果ActivityB为dialog式或者半透明背景呢?
当A跳转B的时候,A先执行onPause,然后B再执行onCreate,onStart,onResume。(注意A的onStop不会执行)
当B按下返回键,B先执行onPause,然后是A只会执行onResume,最后B执行onStop,onDestroy。

只要activity出于可见状态,就不会执行onStop方法。即当前activity再也不可见了,才会回调onStop方法
横竖屏切换
首先Activity页面启动时触发的生命周期
onCreate,onStart,onResume
接着切换成横屏时触发生命周期
omPause,onStop,onDestroy,onCreate,onStart,onResume。
横屏状态下切换至竖屏的变化
onPause,onStop,onDestroy,onCreate,onStart,oResume
竖屏和横屏切换生命周期方法一致,这里并没有在Manifest文件中添加什么配置,接下来我们从Manifest中Activity标签添加如下配置

android:configChanges="orientation|keyboradHidden|screenSize"

当我们再次启动一下看切换横竖屏时生命周期的变化
onCreate,onStart,onResume
接下来切换成横屏
并不会走Activity的生命周期方法,而是回调了一个onConfigurationChanged方法。
这个方法是当系统的配置信息发生改变时,系统会调用此方法

二、Android的启动模式

在这里插入图片描述

2.1 standard

在这里插入图片描述
Standard默认启动模式,(当活动(Activity)处于栈顶时,仍然会继续创建实例)
如果不在AndroidManifest.xml里设置android:lauchMode:" "一般都默认是启动模式是standard。在standard模式下,每当启动一个新的Activity,他就会在返回栈中入栈,并处于栈顶的位置。对于使用standard模式的Activity,系统不会在乎这个Activity是否已经在返回栈中存在,每次启动都会创建一个该Activity的新实例。
例如:
FirstActivity界面

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)
        Log.d("FirstActivity", this.toString())
        button.setOnClickListener {
            var intent = Intent(this, FirstActivity::class.java)
            startActivity(intent)
        }
    }

在这里插入图片描述
从打印信息中可以看出,每点击一次按钮,就会创建出一个新的FirstActivity实例。此时返回栈中也会存在3个FirstActivity的实例,因此你需要连按3次Back键才能退出程序。

2.2 singleTop

在这里插入图片描述
singleTop当活动(Activity)处于栈顶时,可直接使用,不会再创建新的实例,不在栈顶时,但跳转到自己的Activity输出信息时,会自动创建新的实例。
例如:
在AndroidManifest.xml里设置android:lauchMode:"singleTop "
如果还使用上面FirstActivity的代码,只会创建一个实例后面不管你点击多少次按钮都不会有新的打印信息出现。
修改FirstActivity中onCreate()方法的代码
在FirstActivity界面按钮点击进入SecondActivity

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)
        Log.d("FirstActivity", this.toString())
        button.setOnClickListener {
            var intent = Intent(this,SecondActivity::class.java)
            startActivity(intent)
        }
    }

SecondActivity界面点击按钮重新进入FirstActivity

   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        Log.d("SecondActivity", this.toString())
        button2.setOnClickListener {
          var intent=Intent(this,FirstActivity::class.java)
            startActivity(intent)
        }

在这里插入图片描述
可以看到系统创建了两个不同的FirstActivity实例,这是由于在SecondActivity中再次启动FirstActivity时,栈顶Activity已经变成SecondActivity,因此会重新创建一个新的Activity实例。现在按下Back键会返回到SecondActivity,再次按下Back键又会回到FirstActivity,再按一次Back键才会退出程序。

2.3 singleTask

在这里插入图片描述
使用singleTop模式可以很好地解决重复创建栈顶Activity的问题,但是如果该Activity并没有处于栈顶的位置,还是可能会创建多个Activity实例的。借助singleTask模式可以让某个Activity在整个应用程序的上下文中只存在一个实例
例如:
在AndroidManifest.xml里设置android:lauchMode:"singleTask "
在FirstActivity中添加onRestart()方法,并打印日志

    override fun onRestart() {
        super.onRestart()
        Log.d("FirstActivity", "onRestart")
    }

在SecondActivity中添加onDestory()方法,并打印日志

    override fun onDestroy() {
        super.onDestroy()
        Log.d("SecondActivity", "onDestroy")
    }

重新运行程序,在FirstActivity界面点击按钮进入SecondActivity,然后在SecondActivity界面中点击按钮,又会重新进入FirstActivity。
在这里插入图片描述
从打印的信息可以明显看出,在SecondActivity中启动FirstActivity时,会发现返回栈中已经存在一个FirstActivity的实例,并且是在SecondActivity的下面,于是SecondActivity会从返回栈中出栈,而FirstActivity重新成为了栈顶Activity,因此FirstActivity的onRestart()方法和SecondActivity的onDestroy()方法会得到执行,现在返回栈中只剩下一个FirstActivity的实例了,按一下返回键就可以退出程序了。

2.4 singleInstance

在这里插入图片描述
标记singleinstance的SecondActivity会自己创建一个栈,而默认启动模式standard的组在一起一个栈,当返回时,最先返回的是默认启动模式的ThirdActivity然后才是FirstActivity最后是SecondActivity。
指定为singleInstance模式的Activity会启用一个新的返回栈来管理这个Activity(其实如果singleTask模式指定不同的taskAffinity,也会启动一个新的返回栈)。假设我们的程序中有一个Activity时允许其他程序调用的,如果想实现其他程序和我们的程序共享这个Activity实例,使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自己的返回栈,同一个Activity在不同的返回栈中入栈时必然创建了新的实例。而使用singleInstance模式就可以解决这个问题,在这种模式下,会有单独的返回栈来管理这个Activity,不管是哪一个应用程序来访问这个Activity,都共用同一个返回栈,也就解决了共享Activity实例的问题。

例如:
在AndroidManifest.xml里设置android:lauchMode:"singleInstance "

修改FirstActivity中onCreate()方法的代码:

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)
        Log.d("FirstActivity", "Task id is $taskId")
        button.setOnClickListener {
            var intent = Intent(this,SecondActivity::class.java)
            startActivity(intent)
        }
    }

这里我们在onCreate()方法中打印了当前返回栈的id。注意taskId调用的是父类的getTaskId()方法。然后修改SecondActivity中的onCreate()方法的代码:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        Log.d("SecondActivity","Task id is $taskId")
        button2.setOnClickListener {
          var intent=Intent(this,ThirdActivity::class.java)
            startActivity(intent)
        }
    }

同样在onCreate()方法中打印了当前返回的id,然后又修改了按钮点击事件的代码,用于启动ThirdActivity。最后修改ThirdActivity中的onCreate()方法的代码:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_third)
        Log.d("ThirdActivity", "Task id is $taskId")
    }

现在运行程序,在FirstActivity界面中点击按钮进入SecondActivity,然后在SecondActivity界面点击按钮进入ThirdActivity。
在这里插入图片描述
可以看到,SecondActivity的Task id不同于FirstActivity和ThirdActivity,这说明SecondActivity确实是存放在一个单独的返回栈里的,而且这个栈只有SecondActivity这一个Activity。
然后我们按下Back键进行返回,你会发现ThirdActivity竟然直接返回到FirstActivity,再按下Back键又会返回到SecondActivity,再按下Back键才会退出程序,这是为什么呢?其实原理很简单,由于FirstActivity和SecondActivity是存放在同一个返回栈里的,当在ThirdActivity的界面按下Back键时,ThirdActivity会从返回栈中出栈,那么FirstActivity就成为了栈顶Activity显示在界面上,因此也就出现了从ThirdActivity直接返回到FirstActivity的情况。然后在FirstActivity界面再次按下Back键,这时当前的返回栈已经空了,于是就显示了另一个返回栈的栈顶Activity,即SecondActivity。最后一次按下Back键,这时所有的返回栈已经空了,自然退出了程序。

Activity不同启动模式常见应用场景
standard:默认

singleTop:在通知栏点击收到通知,然后需要启动一个Activity,这个Activity就可以使用singleTop,否则每次点击都会新建一个Activity。

standTask:在大多数app的主页,对于大部分应用**,当我们在主界面点击返回按钮都是退出应用,那么当我们第一次进入主界面后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶**,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能被销毁。

singleInstance:使用与程序分离开的页面,比如呼叫来电界面

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值