Android 学习笔记六:Activity 生命周期

活动声明周期

先看一张官方的图
活动生命周期图
这个图显示的是一个Android应用从启动到销毁的整个生命周期。从左边启动,到最右边销毁。

安卓应用一般会有多个Activity,这些Activity会按照启动的先后顺序组成一个栈,最先启动的在栈底,最后启动的也就是当前显示的在栈顶。每次用户看到的就是栈顶的一个Activity。
当新创建一个Activity的时候,会被push到栈顶,退出之后会被弹出。

一个安卓应用会有六种不同的状态,不过其中 createdstarted 只是启动应用的一个瞬间状态,destroyed是被回收前的一个状态,不会持续很长时间。所以长时间的状态只有三种:

  • resumed 正在运行中,可见并且可以交互,也就是处于栈顶
  • paused 暂停,只有当一个新的活动盖在它之上,并且新的活动由于是半透明或者不全屏等原因导致它还能被看到的时候才会处于暂停状态。可见但是不可交互。并且不会执行任何代码了。
  • stopped 停止了,不可见,不可交互,也就是完全被其他活动盖住了。这种情况下,活动的状态(数据等)还是被保留的,但是不会执行任何代码了。

配置Launcher

当用户点击主屏幕上的应用图标的时候,系统会调用制定的主活动onCreate 方法来启动应用,这个主活动 我们称之为 launcher activity。在 AndroidManifest.xml 中这样配置主活动:

<activity android:name=".MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

如果上面的 MAINLAUNCHER 都没有指定,那么你的应用就不会出现在主屏上。

创建Activity

任何时候创建一个activity 实例的时候,系统都是通过调用 onCreate 放来来创建的。所以那些在活动的整个生命周期中只执行一次的一些逻辑应该写在 onCreate 方法中,比如一些初始化配置。比如下面这样:

TextView mTextView; // Member variable for text view in the layout

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set the user interface layout for this Activity
    // The layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.main_activity);

    // Initialize member TextView so we can manipulate it later
    mTextView = (TextView) findViewById(R.id.text_message);

    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // For the main activity, make sure the app icon in the action bar
        // does not behave as a button
        ActionBar actionBar = getActionBar();
        actionBar.setHomeButtonEnabled(false);
    }
}

onCreate 执行完之后,系统会迅速顺序调用 onStartonResume 方法。所以活动不会长时间停留在 created 或者 started 状态。

系统调用onCreate 方法会传入一个 savedInstanceState 参数,这个参数是用来在销毁之后重新创建活动用的。

销毁活动

一个活动的生命周期从 onCreate 开始,到 onDestroy 结束。一般情况下都不需要实现 onDestroy 方法,因为系统会自动销毁 class 引用。大部分的清理工作应该放在 onPausedonStoped 方法中。不过,如果你的活动中包含一些后台线程或者其他可能导致内存泄露的资源,那么你需要在 onDestroy 方法中销毁他们。

正常情况下,系统都会先调用 onPausedonStop 方法,然后再调用 onDestroy 方法。但是有一种例外情况,就是你在 onCreate 中通过调用 onFinish 方法直接结束活动,这个时候因为活动仅仅处在 created 状态,所以系统会直接调用 onDestroy 方法来销毁,而不会调用 onPausedonStop 方法。

暂停和恢复活动

当一个活动被另一个活动部分遮盖的时候,比如启动了一个新的半透明的活动,那么被遮住的活动会进入 paused 状态。如果完全被遮住,则进入 stop 状态。

当一个活动进入 paused 状态的时候,系统会调用 onPaused 方法,你可以在这个方法中停止一些在暂停状态不需要做的事(比如播放视频),或者是保存一些必要的数据以免应用退出之后无法恢复状态。
如果一个活动处在 paused 状态,当用户再次返回这个活动的时候,会调用 onResume 方法。

onPause 方法调用的时候,可能意味着用户暂时离开了这个活动,也可能是用户即将退出应用,当然更多情况下还是意味着用户离开了这个活动,并且这个活动将很快进入 stoped 状态。一般情况下你在 onPaused 方法中需要做这些事:

  • 停止一些正在进行的消耗CPU的任务,比如动画和视频
  • 保存一些没提交的修改。注意,请确认是是用户需要保存的,不是任何修改都需要在这里保存。
  • 释放系统资源,比如GPS等

例如当前活动在使用 camera ,那么在 onPause 方法中你应该释放相机资源:

@Override
public void onPause() {
    super.onPause();  // Always call the superclass method first

    // Release the Camera because we don't need it when paused
    // and other activities might need to use it.
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

注意,一般情况下你不应该onPause 方法中持久化保存用户的修改,除非你确定用户需要自动保存(比如邮件草稿)。但是,onPause 方法中应该避免任何消耗CPU的任务,比如写数据库,因为这样会导致切换活动变卡。

当活动从暂停状态恢复运行的时候,系统会调用 onResume 方法。每次活动从后台变到前台的时候都会执行这个方法,所以你应该在这个方法中初始化你在 onPause 中释放的那些资源,以及一些每次恢复活动都要进行的初始化操作。

@Override
public void onResume() {
    super.onResume();  // Always call the superclass method first

    // Get the Camera instance as the activity achieves full user focus
    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera init
    }
}

上例中是重新初始化在 onPause 中释放的相机。

停止和恢复活动

注意和上面的区别,这里是停止而不是暂停。

这些情况下会导致活动停止:

  • 用户切换到了其他应用。那么你的应用中的前台活动就会进入停止状态。当用户返回的时候就会 restart
  • 创建了一个新的活动,那么当前的活动就会进入停止状态。
  • 用户接听电话。

当进入暂停状态的时候,表示当前活动已经完全不可见。

一个活动进入停止状态的时候会依次调用 onPauseonStop 方法。恢复运行的时候会依次调用 onStartonResume 方法。

因为在停止状态的时候,系统还是保留了当前活动的实例(只有销毁才会从内存中删除),所以很多时候你并不需要实现 onStartonStop 方法,你只需要实现 onPauseonResume 即可。

当活动被调用 onStop 的方法的时候,已经是完全不可见状态,应该释放所有不需要的系统资源。如果一个活动处在 stopped 状态,那么当系统内存不足的时候,极端情况下,系统甚至不调用 onDestroy 方法而直接杀掉进程,所以一定要在 onStop 方法中释放系统资源

前面说过不应该在 onPause 方法中执行耗时的任务,那么你应该在 onStop 中执行这些任务,比如写数据库。

当活动处在 stopped 状态的时候,活动的实力依然存在内存中。你不需要重新初始化那些在 onCreateonResume 之间初始化过的组件。系统也会自动保存所有的 View状态,比如用户在文本框中输入的内容依然会保留。

销毁和重新创建活动

当用户旋转屏幕的时候,系统会销毁并重新创建前台活动。

默认情况下,系统在销毁活动的时候会使用 Bundle 来保存活动中View的状态,并且在重新启动的时候自动恢复。但是如果你有除了 View 以外的其他数据需要保存的时候,你就需要自己写代码了。

注意Android是通过 id 来保存活动信息的,所以请确保你的每一个活动都有一个唯一的id,通过 android:id 来设置。

如果你需要保存额外数据,那么应该重写 onSaveInstanceState() 方法。系统在销毁活动的时候会自动调用这个方法,并且传入一个 Bundle 对象。当系统重新创建活动的时候,会把同样的 Bundle 对象作为参数传入,注意这个时候在 onCreateonRestoreInstanceState() 方法中都会传入。

当系统销毁活动的时候,这样保存数据:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

当系统重新创建活动的时候,会给 onCreate 传入上面的 Bundle 对象。但是因为第一次创建也是调用 onCreate 方法,所以在 onCreate 方法中使用 bundle的时候请先检查是否为空:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

另外系统还会调用 onRestoreInstanceState() 方法,并且只有 bundle 不为空的时候才会调用,因此你可以重写这个方法而不用检查 bundle 是否为空:

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
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值