3.4--Activity 的生命周期

3.4.1 返回栈

Android 是使用任务(task) 来管理Activity 的,一个任务就是一组存放在栈里的Activity的集合,这个栈也被称作返回栈(back task)。栈是一种先进后出的数据结构,在默认情况下每当我们启动了一个新的 Activity ,它就会在返回栈中入栈,并处于栈顶位置。每当我们按下Back 键或者调用 finish() 方法去销毁一个Activity 时,处于栈顶的Activity 就会出栈,前一个入栈的Activity 就会重新处于栈顶的位置。系统总是会显示处于栈顶的Activity 给用户。

3.4.2 Activity 状态

每个Activity 在其生命周期中最多可能会有4个状态。

1、运行状态:位于返回栈栈顶。系统基本不会回收这个Activity。

2、暂停状态:不在栈顶,但是可见!内存极低的情况系统会回收。

3、停止状态:不在栈顶,完全不可见。系统需要内存时候有可能回收,不太稳定。

4、销毁状态:从返回栈移除后,就变成销毁状态,系统最倾向优先回收这种状态的Activity。

3.4.3 Activity 的生命周期

Activity类定义了7个回调方法,覆盖了生命周期的每个环节:

onCreate:第一次创建Activity 调用。

onStart:由不可见变为可见调用。

onResume:Activity 位于栈顶,而且处于运行状态调用。

onPause:系统准备去启动或者恢复另一个Activity 的时候调用,可以用来释放CPU 资源,以及保存关键数据,但是要保证执行速度,否则会影响用户体验和新的栈顶Activity 的使用。

onStop:完全不可见,如果启动的新Activity是对话框Activity,那么这个方法不会调用,因为对话框Activity 不会完全遮挡屏幕。

onDestroy:被销毁之前调用。之后Activity 状态进入被销毁状态。可以用来释放资源。

onRestart:由停止状态变为运行状态之前调用,会调用onStart 依次排列调用,在完全不可见状态下恢复就会调用。

如果Activity 被杀掉进程后想要恢复调用,那么就会直接进入onCreate。

Activity 可以分为三种生存期:

完整生存期 onCreate --> onDestroy 生存到销毁。

可见生存期 onStart ~ onStop 之间就是可见的,但是还不能和用户交互。

前台生存期 onResume ~ onPause 之间是可见的,可以和用户交互。

 

3.4.4 体验Activity 的生命周期

我们新建个demo 进行演示。

首先我们创建一个ActivityLifeCyeleTest 项目,然后再创建两个Activity ,分别为NormalActivity 和DialogActivity  。DialogActivity 设置主题为Dialog 对话框Activity。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitylifecycletest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".DialogActivity"
            android:theme="@style/Theme.AppCompat.Dialog"
            android:label="DialogActivity"
            ></activity>
        <activity android:name=".NormalActivity"
            android:label="NormalActivity"
            />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我们在MainActivity 的布局文件中添加两个 Button 按钮进行做每个Activity 的跳转事件。然后重写声明周期方法,并且通过Log 打印出来:

class MainActivity : AppCompatActivity() {
    private val tag = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(tag,"onCreate")
        startNormalActivity.setOnClickListener { 
            val intent = Intent(this,NormalActivity::class.java)
            startActivity(intent)
        }
        startDialogActivity.setOnClickListener {
            val intent = Intent(this,DialogActivity::class.java)
            startActivity(intent)
        }
    }

    override fun onStart() {
        Log.d(tag,"onStart")
        super.onStart()
    }

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

    override fun onResume() {
        Log.d(tag,"onResume")
        super.onResume()
    }

    override fun onPause() {
        Log.d(tag,"onPause")
        super.onPause()
    }

    override fun onStop() {
        Log.d(tag,"onStop")
        super.onStop()
    }

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

这里我们就可以用来测试和打印生命周期的顺序了。当MainActivity 第一次运行的时候执行的生命周期顺序为,onCreate -- onStart --  onResume,当我们点击Start NormalActivity  按钮的时候MainActivity 会执行 onPause 和 onStop 方法,因为NormalActivity 启动会直接遮挡MainActivity 所以会调用onStop ,当我们使用Back 键返回的时候,MainActivity 会调用onRestart -- onStart -- onResume ,如果我们启动了DialogActivity ,我们的MainActivity 会只调用onPause  因为DialogActivity 并不是全屏显示的,我们还可以看见MainActivity 所以MainActivity 不会执行onStop 方法。最后按下Back 结束应用。MainActivity 会执行,onPause -- onStop -- onDestroy

 

3.4.5 Activity 被回收了怎么办

当一个Activity 进入停止onStop 状态后是可能被系统回收的。如果从 Activity  A 进入B ,此时A被系统回收,这个时候按下Back 按键会出现什么情况?这个时候就会从A 的onCreate 方法开始重新创建一次。

如果这个页面有用户的临时数据怎么办?重新创建就意味着临时数据的丢失,是会比较影响用户体验的,在Activity 中还提供了一个onSaveInstanceState 回调方法。这个回调方法可以保证在Activity 被回收之前一定被调用。onSaveInstanceStata会携带一个Bundle 的参数,我们可以把数据存放在Bundle 对象中,存储方式是键值对。

override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
        super.onSaveInstanceState(outState, outPersistentState)
        val tempData = "Something you just typed"
        outState.putString("data_key",tempData)
    }

这个方式存储的数据我们要怎么获取呢?就是onCreate 回调中的Bundle 类型的参数。如果触发了 onSaveInstanceState 后恢复了Activity 那么onCreate 中的 Bundle 参数就不会是空的!我们就可以拿到我们之前存储的数据。

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(tag,"onCreate")
        savedInstanceState?.let {
            val tempData = it.getString("data_key")
            Log.d(tag,tempData)
        }
}

这里要说明一下,手机旋转也会触发Activity 的重新创建过程,Activity 的数据也会丢失。虽然可以通过这种方式进行保存数据,但是我们会有更高级的方式来解决这个问题,这个在后面会说。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值