2019-05-08

2019-05-08  本文已影响0人  叶一帆6

Activity生命周期

(一)简介

onCreate()
在系统创建活动时触发;

onStart()
作为onCreate()退出时,活动进入开始状态,并且activity变得对用户可见;

onResume()
当一个活动和用户发生交互的时候,触发该方法。此时,activity位于activity堆栈的顶部,并捕获所有用户输入。应用程序的大多数核心功能是在此方法中实现的。

onPause()
当活动失去焦点并进入暂停状态时,系统会调用。例如当用户点击“后退”或“最近”按钮时,会出现此状态。
当系统调用此方法时,通常表示用户正在离开此activity(文档中表示为partially visable,也就是部分可见),并将很快进入“已停止”或“已恢复”状态。在一些场景下会需要调用此方法:示出(也就是该activity不被显示在屏幕上时)导航地图屏幕或媒体播放器播放的活动。即使这些活动失去焦点,用户也希望它们的UI继续更新。

你不应该在此方法中保存应用程序或用户数据,进行网络通话,或执行数据库事务。
一旦onPause()完成执行,下一个回调是onStop()或onResume(),视activity进入暂停状态后发生的情况而定。

onStop()
当活动不再对用户可见时调用。
此方法被调用的情况有:activity正在被破坏,新activity正在开始,或现有activity正在进入恢复状态并且覆盖已停止的活动。
如果内存紧张,系统会直接结束这个活动,而不会触发 onStop 方法。 所以保存状态信息是应该在onPause时做,而不是onStop时做。

onRestart()
当处于“已停止”(Stop)状态的activity即将重新启动时,系统将调用此方法。此回调始终紧跟着onStart()后发生。

onDestory()
此方法在销毁activity之前被调用。通常实现以确保在activity或包含它的进程被销毁时释放所有活动的资源。

==额外:==
onSaveInstanceState() :系统调用该方法,允许活动保存之前的状态,比如说在一串字符串中的光标所处的位置等。
通常情况下,开发者不需要重写覆盖该方法,在默认的实现中,已经提供了自动保存活动所涉及到的用户界面组件的所有状态信息。

(二)Activity状态

一般认为Activity有以下四种状态

(三)后台堆栈模型

注意:可以在后台同时保存多个任务。但是,如果用户同时运行许多后台任务,系统可能会开始销毁后台活动以恢复内存,从而导致活动状态丢失。

(四)管理任务

定义启动模式

启动模式允许您定义活动的新实例与当前任务堆栈的关联方式。您可以通过两种方式定义不同的启动模式:使用清单文件或使用Intent标志。(清单文件Manifest.xml优先级高一些)

使用清单文件定义启动模式:

在清单文件中声明活动时,可以使用<activity> 元素的launchMode属性指定活动应如何与任务关联。其有四种不同的启动模式:

注意:虽然activity在新任务中启动,但“后退”按钮仍会将用户返回到上一个activity。

实例
  1. 假设任务的后台堆栈由根活动A组成,其中活动B,C和D位于顶部(堆栈为ABCD; D位于顶部)。意图到达类型D的活动。如果D具有默认"standard"启动模式,则启动该类的新实例并且堆栈变为ABCDD。但是,如果D的启动模式是"singleTop",D的现有实例接收意图onNewIntent(),因为它位于堆栈的顶部 - 堆栈仍然是ABCD。但是,如果意图到达类型B的活动,则将新的B实例添加到堆栈中,即使其启动模式为"singleTop"。
  2. Android浏览器应用程序声明Web浏览器活动应始终在其自己的任务中打开 - 通过singleTask在<activity>元素中指定启动模式。这意味着,如果您的应用发出打开Android浏览器的意图,则其活动不会与您的应用放在同一任务中。相反,要么为浏览器启动新任务,要么如果浏览器已经在后台运行任务,则该任务将被提前处理新意图。 实例2

    无论活动是在新任务中启动还是在与启动它的活动相同的任务中启动,“ 返回”按钮始终会将用户带到上一个活动。但是,如果启动指定singleTask启动模式的活动,则如果后台任务中存在该活动的实例,则将整个任务带到前台。此时,后端堆栈现在包括在堆栈顶部提出的任务中的所有活动。上图说明了这种情况。

使用Intent标志定义启动模式

启动活动时,您可以通过在传递到的intent中包含标志来修改活动与其任务的默认关联。您可以用来修改默认行为的标志是:

intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

启动模式的区别

启动模式的介绍:堆栈与启动模式

四种加载模式的区别:

(五)处理activity状态更改

发生配置更改

有许多事件可以触发配置更改。最突出的例子是屏幕纵向和横向之间的变化。其他情况包括更改语言或输入设备。
发生配置更改时,将销毁并重新创建activity。原来的activity实例对象的onPause()、onStop()和onDestory()方法将被触发。而activity的一个新实例将被创建(也就是onCreate()、onStart()和onResume()方法会被触发)。
可以使用ViewModel,onSaveInstanceState()方法和持久本地存储的组合来保持activity在配置更改中的UI状态。这里需要根据App情况进行选择。

activity或对话框出现在前台(foreground)

这里有两种情况:

注意:当用户点击“概览”或“主页”按钮时,系统的行为就像当前活动已完全覆盖一样。

用户点击后退按钮(Back button)

如果activity是在前台,而用户点击后退按钮(回到桌面或主页面),该activity通过调用onPause()、onStop()和onDestory()方法。除了被销毁之外,activity也从后台堆栈中移除。
==要注意的是:==默认情况下,onSaveInstanceState()在这种情况下不会触发。但可以在这种情况下覆盖该****onBackPressed()以实现某些自定义行为,例如“确认退出?”对话框。

系统会杀死应用程序进程

如果应用程序在后台并且系统需要为前台应用程序释放额外的内存,则系统可以终止后台应用程序以释放更多内存。

==补充==:onSaveInstanceState()被触发的条件

static final String STATE_SCORE = “playerScore” ;   
static final String STATE_LEVEL = “playerLevel” ;   

@Override
public void onSaveInstanceState (Bundle savedInstanceState ){  
    //保存用户当前的游戏状态
    savedInstanceState.putInt (STATE_SCORE ,currentScore );
    savedInstanceState.putInt (STATE_LEVEL ,currentLevel );

    //始终调用超类,以便保存视图层次结构状态
    super.onSaveInstanceState (savedInstanceState );
}

注意: 当用户显式关闭活动时或当finish()被调用时,onSaveInstanceState()不会被回调

要保存持久性数据(例如用户首选项或数据库的数据),您应该在活动位于前台时采取适当的机会。如果没有这样的机会,您应该在onStop()方法期间保存这些数据 。

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    currentScore = savedInstanceState.getInt(STATE_SCORE);
    currentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

(六) Activity生命周期交互

多个Activity之间切换时的状态变化

疑问:在打开新的Activity时,为什么不执行当前activity的onPause()和onStop()方法,而是将二者分别在要跳转的activity的三个方法执行前后调用?
答案:onPause()方法一般用于关闭当前Activity的视频音频,或者其他可能妨碍到新的Activity的功能(比如接电话等)。还可以在跳转到新的Activity前保存当前Activity的一些状态信息等。而在第二个Activity完全加载之后才执行原Activity的onStop()方法,这个设计主要是为了防止当第二个Activity在加载时出错出现闪退等异常时,第一个Activity还能够显示在屏幕上,而不是“不可见状态”。所以说这是一种考虑了很多情况的设计。

横竖屏切换时的状态变化

横竖屏切换时,系统会在当前Activity依次执行onPause()、onStop()和onDestory(),然后再重新创建。若想要在切换前后有一致的UI状态,就需要重载onSaveInstanceState(Bundle outState)方法来将信息保存进outState中,然后在onRestoreInstanceState中还原。

生命周期应用场景

媒体播放器播放时跳转到其他Activity

假如当前Activity在播放着音乐,突然一个电话过来,那么用户肯定是想当前音乐停止然后切换到电话界面,当电话结束后回退到原来界面时,继续从刚才的地方播放音乐。根据第一条中的情景二,我们知道此时需要分别在onPause()和onResume()方法中实现一些操作。

Activity启动的另一种方式:匿名启动

如下所示,在Manifest.xml文件中,我们可以在<intent-filter>中插入<action>b并添加属性android:name,这样别的Activity就可以通过这个名字来start此Activity,而不是通过Activity真实的类名(在调用其他App的界面时会使用到,自己的App内部没必要用这种方式)。

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="jieko" /> //这里可以为此Activity生成自定义的名字
                //category指定Activity启动的环境
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter>
        </activity>

//调用方式:
        Intent intent = new Intent();
        intent.setAction("jieko");
        startActivity(intent);

还可以通过上面的“调用方法”调用一些系统内置的一些应用,比如浏览器、图库、相机、短信、电话等等。示例如下:

        //调用浏览器
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW); //Intent中内置有一些常量,用来调用系统app
        Uri uri = Uri.parse("...");
        intent.setData(uri);
        startActivity(intent);
上一篇下一篇

猜你喜欢

热点阅读