四大组件之Activity

生命周期

这里写图片描述

onCreate()
onRestart()
onStart()

Activity开始对用户可见时调用。

onResume()

Activity开始和用户进行交互,此时Activity是在栈顶。

onPause()

Activity失去焦点,不能与用户交互,但对用户还是可见的。
系统要开始恢复一个之前的Activity时调用。主要用来提交未保存的改变,停止动画或其他消耗CPU的事情。在此方法中的操作要迅速,因为接下来的Activity不会被创建直到该方法执行完成。
在Android 3.0之前,该状态下的Activity是可以被kill掉的。

注意:要清楚知道什么时候在onPause()中持久化数据,什么时候在onSaveInstanceState(Bundle)中持久化数据。onSaveInstanceState(Bundle)不是Activity生命周期的一部分,所以它不会总是被调用。

onStop()

当Activity不再对用户可见时调用。

onDestory()

Activity A启动 Activity B时的两者生命周期的变化

  1. Activity A的onPause()被调用
  2. Activity B的onCreate()onStart()onResume()依次被执行
  3. Activity A的onStop()被调用

状态保存

这里写图片描述

onSaveInstance()一定会在onStop()之前被调用,但不确定是否是在onPause()之前。
onSaveInstance()不一定会被调用,例如当用户通过返回键退出Activity时,用户的意图就是关闭Activity,那么Activity就没有必要保存状态了,从而就不会调用onSaveInstance()
onRestoreInstanceState()onStart()之后,onPostCreate()之前被调用。
onPostCreate()通常不会由我们去实现。在我们的代码运行完成之后,系统会使用这个方法去做最后的初始化。

默认地,Activity会保存一些相关状态(已声明了id的View的状态,例如:EditTextView的已输入的文本等),但Activity是不会自动帮我们保存我们自定义的状态的。所以我们需要在onSaveInstance()onRestoreInstanceState()中保存和恢复状态。有时我们不会使用onRestoreInstanceState()方法恢复状态而是在onCreate()中恢复状态。

我们可以使用android:saveEnabledsetSaveEnabled()禁用掉View的自动保存状态。
我们可以通过旋转屏幕的方式去测试Activity是否能够正确地恢复它的状态。
屏幕翻转,Activity重建,如果保持翻转后的状态,那么之前的activity也会重新创建;如果又翻转回来,那么之前的activity不会重新创建。

运行时改变

主要指的是屏幕旋转和语言切换,当然还有其他一些改变。
运行时改变会导致Activity被销毁掉并立即重新创建一个新的Activity。

android:configChanges="keyboardHidden|screenSize|orientation"

四种运行模式

  1. Standard
    Activity能够实例化多次,每个实例可以属于不同的task,一个task可以有多个实例。
    默认Activity存放在其启动它的Task栈中,但是在5.0之后就变为在其默认的栈中。
  2. SingleTop
    与Standard类似,只有一种情况例外:Activity位于当前task的栈顶,那么Activity不会创建一个新的实例,而是重用栈顶的Activity,然后onNewIntent()会被调用。
  3. SingleTask
    如果没有task中有此Activity实例,那么就创建一个新的task并将Activity的实例作为这个task的栈顶元素。
    如果有task中有此Activity实例并且该task位于后台,那么这个task就会被带回到前台,同时如果此Activity实例不是出于栈顶则会清除其之上的Activity。然后当用户点击返回键时,返回的Activity不是之前的Activity而是处于这个SingleTask的Activity的之下的Activity。
    该Activity只有一个实例存在。

注1: 如果Activity已存在但不是在一个task的栈顶,而是在栈中间,那么情况会是什么样呢?结果是会清除掉其之上的Activity。

注2: 默认情况,如果没有实例,则在当前应用的task中创建实例;如果有实例,则重用并清除在其之上的Activity。

注3SingleTask不适合做启动页的lunchMode,因为当从桌面启动应用时,SingleTask会将其栈顶之上的所有Activity都清除掉。而SingleTop却不会。但是如果外部应用开启本应用的话,那么外部应用开启本应用是使用外部应用的task栈,在Android5.0之后就是新开启一个task栈了。
SingleTop本身是不会将后台task栈带回到前台的,这里是结合了FLAG_ACTIVITY_NEW_TASK的使用,才会实现从桌面启动应用时将应用从后台带回到前台同时又不会清除启动Activity之上的Activity。

  1. SingleInstance
    与SingleTask类似,但Activity是SingleInstance时,Activity所在的task只有此Activity一个实例,不会有其他Activity的实例。即,Activity是task中的唯一成员。

上述四种运行模式是Activity在AndroidManifest.xml中声明时所使用的。还有三种Intent Flags可以影响Activity的行为。

  1. FLAG_ACTIVITY_NEW_TASK
    行为与SingleTask一致,但如果该Activity并不在栈顶的话却不会清除其上的Activity。
    该Flag与FLAG_ACTIVITY_CLEAR_TOP合用时才会产生SingleTask的行为。
  2. FLAG_ACTIVITY_SINGLE_TOP
    行为与SingleTop一致。
  3. FLAG_ACTIVITY_CLEAR_TOP
    如果想要开启的Activity已经存在于当前的task中,那么就会重用它,并清除掉栈中之前的Activity。
    注4:如果Activity是“standard”的,那么该Activity实例也会被移除,然后一个新的Activity实例被运行并放在栈中的此处。这是因为“standard”的行为就是为每一个新的Intent创建一个新的实例。也就是说如果MainActivity是‘standard’, 那么 FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TOP结合使用时并不会重用MainActivity,而是重新创建一个实例。而要重用MainActivity则只需 SingleTopFLAG_ACTIVITY_CLEAR_TOP即可。
    注5:通过“注4”我们会发现,在使用flag时要注意launchMode的影响。

TaskAffinity(<activity>属性)

这个属性表明一个Activity属于哪个task,下面是默认设置: 1. 每个Activity都有一个taskAffinity值,默认是application的taskAffinity, 2. Application的taskAffinity默认是应用的包名 3. 每个task都有一个taskAffinity,该值与Activity栈中的栈底的Activity的taskAffinity值一致 我们可以修改默认设置,不同应用的Activity能够共享一个affinity,同一个应用的Activity也可以指定给不同的task affinity。 该属性值是String类型,并且必须是唯一的,不能使包名(因为默认就是包名),并在以下两种情况下发挥作用: 1. 当运行Activity的Intent包含`FLAG_ACTIVITY_SINGLE_TSK`时 默认情况下一个新的Activity是运行在与调用者相同的task中的。而通过一个包含`FLAG_ACTIVITY_SINGLE_TASK`的Intent启动的Activity的话,系统会为这个Activity寻找一个不同的task,经常是一个新的task。但是只有当不存在一个与新Activity的affinity同名的task时,才会使用一个新的task;如果存在,则新的Activity会运行在这个已存在的task中。 2. 当Activity的`allowTaskRepeating`属性为`true`时 当它喜欢的task来到当前台时,Activity可以从它开启的task移动到它`喜欢(has an affinity for)`的task上。

清除back stack

默认,如果用户离开一个task很长一段时间的话,系统就会清除除Root Activity之外的所有Activity。当用户再回来的时候,只有Root Activity被恢复。接下来的几个属性可以修改此默认行为:
1. alwaysRetainTaskState
如果将Root Activity的该属性设置为true的话,那么就会保留所有的Activity。
2. clearTaskOnLaunch
如果将Root Activity的该属性设置为true的话,那么无论在什么时候都只会保留Root Activity,即使用户只离开了一小会儿。
3. finishOnTaskLaunch
与clearTaskOnLaunch类似,但该属性只作用于一个Activity,而不是一个task。该属性能够引起任何一个Activity(包括Root Activity)被杀掉。

onActivityResult

如果在AndroidManifest文件中指定Activity的`noHistory`为true,那么`onActivityResult`方法就不会被调用。 当Activity restart时,`onActivityResult`会在`onResume`之前被调用。 **宿主是FragmentActivity** 如果在`Fragment`中直接调用`startActivityForResult`,则`Fragment`先接收到,其次是`Activity`接收。 如果调用`getActivity().startActivityForResult()`,则`Activity`接收到,`Fragment`接收不到。 **宿主是Activity** 如果在`Fragment`中直接调用`startActivityForResult`,则只有`Fragment`接收到。 如果在`Fragment`中直接调用`getActivity().startActivityForResult()`,则只有`Activity`接收到。 **onActivityResult无效**

Note that this method should only be used with Intent protocols that are defined to return a result. In other protocols (such as ACTION_MAIN or ACTION_VIEW), you may not get the result when you expect. For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result.

所以当通过`startActivityForResult(new Intent(Intent.ACTION_VIEW), 11)`时,才会立即接收到一个cancel。

其他

  1. 要想在点击Notification时开始一个Activity的话,那么这个Activity需要声明exported=”true”
  2. SingleTask之谜
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值