Activity生命周期与启动模式

Activity作为四大组件之首是使用最为频繁的组件,它主要是负责呈现界面,为用户提供可用的操作或是运行的结果。其中,关于Activity的生命周期一直都是比较重要的知识点。本次我主要是学习了Activity的生命周期与启动模式,将了解到的相关知识记录在此。

一、Activity的生命周期

首先,先看一下官方的Activity的生命周期图


Activity生命周期中调用的方法的分析:

1、onCreate:表示Activity正在被创建,这是生命周期的第一个方法,在这个方法中,我们需要做一些必需的初始化工作,比如调用setContentView去加载界面的布局资源、初始化Activity所需要的数据等等。在整个生命周期中,onCreate只调用一次。

2、onStart:表示Activity正在被启动,Activity进入可见状态,但是还没有出现在前台,无法和用户进行交互,无法获得焦点,触发事件。

3、onResume:表示Activity已经可见了,获得了焦点,能够和用户进行交互,在这里能够看到最终的布局效果,能够触发事件。此刻的Activity处于Activity栈的顶端,等待与用户发生交互。(每当界面重写调回或者重启时会调用此方法)

4、onPause:调用此方法后,Activity进入暂停状态,此时。当前的Activity不能进行交互,也就是说不能相应用户操作。但是,在这个时候,Activity还是可以看到的,在这里,可以做一些存储数据的工作,也可以暂停动画等界面效果,比如触发了对话框,或者被锁屏,但是需要注意的是,不能太耗时,因为这会影响到新的Activity的显示,onPause必须执行完毕,新的Activity的onResume才会执行。

5、onStop:表示Activity即将停止,在这里,应该保存数据,停止一些消耗资源的事件,防止在不可见的状态下被回收。比如转到其他Activity的界面,或者被后台执行。同样的在这里也不能太耗时。

6、onDestroy:Activity即将被销毁,这是Activity生命周期的最后一个操作,这个方法将销毁所有视图,在这里应该释放一切占用的资源,比如停止播放、网络请求等所有操作。也可以做一些回收的工作。此方法与onCreate方法一样,在Activity生命周期中只会调用一次。

7、onRestart:表示Activity正在重新启动,当前Activity从不可见重新变为可见状态时,onRestart方法就会被调用。这种情况一般是用户行为所导致的,比如用户按HOME键切换到桌面或者是重新打开一个新的Activity,这时,当前的Activity就会暂停,也就是onPause与onStop被执行了,当用户又重新回到这个Activity时,就会调用onRestart。

以上7重方法都有一个对应:onCreate与onDestroy(创建于销毁);onStar于onStop(启动与停止);onResume与onPause(获取焦点与失去焦点)。


接下来举一个简单的例子来看一下Activity生命周期的运转。

本次所举的例子写了两个Activity,FirstActivity与SecondActivity,代码如下:

activity_first.xml(布局比较简单,页面上只有一个按钮,点击后能够进入SecondActivity页面):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_first"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_next"
        android:layout_width="120dp"
        android:layout_height="60dp"
        android:layout_centerInParent="true"
        android:background="#00ff00"
        android:text="下一页"
        android:textSize="30sp"
        android:gravity="center"/>

</RelativeLayout>

FirstActivity.java(此页面中调用了Activity生命周期的所有方法,待会会根据打印来分析Activity的生命周期过程):

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class FirstActivity extends Activity {
    static final String TAG = "FirstActivity";
    Button btnNext;

    //创建Activity时调用
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        Log.e(TAG, "onCreate");

        btnNext = (Button)findViewById(R.id.btn_next);
        //点击按钮进入下一个SecondActivity
        btnNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

    //销毁Activity时调用
    @Override
    protected void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }

    //启动Activity时调用
    @Override
    protected void onStart() {
        Log.e(TAG, "onStart");
        super.onStart();
    }

    //停止Activity时调用
    @Override
    protected void onStop() {
        Log.e(TAG, "onStop");
        super.onStop();
    }

    //Activity被重新启动时调用
    @Override
    protected void onRestart() {
        Log.e(TAG, "onRestart");
        super.onRestart();
    }

    //获取Activity的焦点
    @Override
    protected void onResume() {
        Log.e(TAG, "onResume");
        super.onResume();
    }

    //暂停Activity,失去焦点
    @Override
    protected void onPause() {
        Log.e(TAG, "onPause");
        super.onPause();
    }

}


activity_second(此布局只有一个TextView):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="第二页"
        android:textSize="50dp"
        android:gravity="center"/>

</LinearLayout>

SecondActivity.java(此页面只负责展示):

public class SecondActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }
}


在手机上运行程序,通过一系列操作查看过程中方法的执行:

1、当应用被安装启动或者被完成销毁后重新启动进入FirstActivity时,执行的方法:


2、当按了HOME键后,返回桌面,进行后台执行时方法(注:如果长时间后台执行,可能会被垃圾回收机制杀死,执行onDestroy()方法)


3、从桌面点击进入FirstActivity时,执行的方法(重新进入FirstActivity界面时,会先执行onRestart,然后再执行onStart):


4、按FirstActivity中的button,跳转到SecondActivity时,执行的方法:


5、从SecondActivity界面按手机的返回按钮,退回到FirstActivity时执行的方法:


6、在FirstActivity界面,手机锁屏时执行的方法:


7、解锁屏幕回到FirstActivity界面是执行的方法:


8、从FirstActivity界面点击手机返回键退到桌面时执行的方法:


从上面可以看出,这些用户操作中,从安装启动FirstActivity到按返回键退出FirstActivity,onCreate与onDestroy只执行了一次,中间所有的过程都是其他方法来回执行


但是当横竖屏切换时,系统会先将FirstActivity销毁,然后重新创建一个新的FirstActivity,执行方法如下:


像这种Activity的状态切换时,会进行重构,其实重新创建的Activity已经不是同一个Activity的实例了,系统并不会为我们保存数据,所以为了避免遇到状态切换时数据被销毁,我们就需要做一些准备工作来保存相关的数据。需要使用onSaveInstanceState()方法进行保存,使用onCreate()与onRestoreInstanceState()方法恢复数据。此项涉及的是Activity的恢复,在这里不多做描述。

以上举的例子就是Activity生命周期的方法执行过程了。


二、Activity的启动模式

启动模式简单的说就是Activity启动时的策略。当我们的应用运行起来后会开启一条线程,线程中会运行一个任务栈,当Activity实例创建后就会放入任务栈中。Activity启动模式的设置在AndroidManifest.xml文件中,通过配置Activity的属性android:launchMode=""来设置启动模式。启动模式有4种:standard、singleTop、singleTask、singleInstance。

对于任务栈,每一个应用都有一个任务栈,是用来存放Activity的,功能类似于函数调用的栈,先后顺序代表了Activity的出现顺序,比如上一个例子中的FirstActivity与SecondActivity,出现顺序为FirstActivity》SecondActivity,相应的任务栈为(先出现的在栈的最下方,启动一个新的Activity时,覆盖前一个Activity):


接下来回详细说一下每一种启动模式:

1、standard

standard模式为默认模式,可以不用进行配置。在这种模式下,每次启动一个Activity,都是重新创建一个新的实例,不管这个实例是否存在。一旦激活该Activity,则会向任务栈中加入新创建的实例,退出则Activity则会在任务栈中销毁该实例。standard模式是所有启动的Activity都是在同一个task容器栈下,不会重新创建新的task容器栈。先压入栈的在栈底,后入的在栈顶,处于栈顶的Activity实例处于活动状态,也就是当前显示的界面,其他的处于非活动状态。


点back键会依照栈顺序依次退出。一层一层的返回。

下面是实例的日志打印(启动过程为FirstActivity》SecondActivity》FirstActivity)


可以看出,每启动一次Activity就会创建一次,不管要启动的Activity实在task的栈底还是栈顶。


2、singleTop

栈顶复用模式,在这种模式下,如果Activity已经于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会被回调,需要注意的是,这个Activity的onCreate、onStart不会被系统调用,因为它并没有发生改变。如果新Activity的实例已经存在但不是位于栈顶,那么新Activity,仍然会重新重建。这种模式有一个好处是防止多次点击创建多个Activity实例。

从图可以看出,栈中Activity3只有一个

清单配置如下:

<activity
android:name="com.itcode.taskstack.SecondActivity"
android:label="@string/app_name"
android:launchMode="singleTop">
</activity>
下面是实例的日志打印先是FirstActivity》SecondActivity》FirstActivity》ThirdActivity》ThirdActivity


第二启动FirstActivity的时候,由于在task中,它不是在栈顶,所以需要重新创建,而第二次启动ThirdActivity的,它是在栈顶,所以直接调用onNewIntent()方法。


3、singleTask

栈内复用模式,是一种单实例模式。如果任务栈中存在该模式的Activity实例,则把栈中该实例以上的Activity实例全部移除,调用该实例的newInstance()方法重用该Activity,使该实例处於栈顶位置,否则就重新创建一个新的Activity实例。


最后执行Activity1时,直接用已有的实例,而Activity2与Activity3都会被移除

清单配置如下:

<activity
android:name="com.itcode.taskstack.SecondActivity"
android:label="@string/app_name"
android:launchMode="singleTask">
</activity>

下面是实例的日志打印先是FirstActivity》SecondActivity》ThirdActivity》FirstActivity


第二次启动FirstActivity的时候。调用的是OnNewIn()方法,并且SecondActivity与ThirdActivity都被销毁额。


4、singleInstance

单实例模式,是singleTask的加强模式,此种模式下的Activity只能单独位于一个任务栈,系统会为它单独创建一个任务栈,后续的请求不会创建新的Activity。singInstance和singleTask主要区别在与系统范围内的“实例唯一”还是当前Activity栈“实例唯一”


清单配置如下:

<activity
android:name="com.itcode.taskstack.SecondActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
</activity>

下面是实例的日志打印先是FirstActivity》SecondActivity》FirstActivity》SecondActivity


当两个都是第二次启动时都调用了OnNewIntent()方法,它们的实例分别在两个task中,且是task中的唯一


其实指定启动模式有两种方法:除了使用上述的使用xml属性android:launchMode之外,还可以使用代码intent.addFlags()。第二种方式优先于第一种,当两种都存在时以第二种为准,第一种不能设定FLAG_ACTIVITY_CLEAR_TOP标识,第二种无法设置singleInstance模式。


Activity的启动模式源代码:ActivityLifeCycle













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值