Android Activity 完全解析(上)

本文深入探讨了Android Activity的生命周期,包括各个状态的转换,如onCreate、onStart、onResume、onPause、onStop和onDestroy。通过示例代码展示了正常启动、切换Activity和横竖屏切换时Activity生命周期的变化,强调了onSaveInstanceState和onRestoreInstanceState在保存和恢复数据中的作用。

       学习 Android 恐怕打交道最多的就是 Activity,只要是我们看到的界面上的东西,几乎都是以 Activity 为载体的,它是一种包含用户界面的组件,用于和用户进行交互,Activity 是基础中的基础,但越是基础的东西,我们就有可能忽视它的重要性,这样我们的基础就会不扎实,所以即使是基础的东西,我们还是很有必要去花时间尽力好好分析一下的,下面我们对活动进行详细的介绍,说到活动恐怕活动的生命周期我们就不得不去研究,来看概览图




Activity 的生命周期全面分析:


一、正常情况下一个 Acitivity 会经历如下的生命周期:


Activity 经典生命周期图,来自 Google 官网


1. 生命周期介绍


1)onCreate

这是 Activity 生命周期的第一个方法,这个方法相信我们已经看到了很多次,每个活动我们都重写了这个方法,它会在活动第一次被创建的时候调用,在这个方法中我们可以去做一些初始化的操作,比如调用 setContentView 去加载页面的布局,初始化 Activity 所需的数据等

2)onStart

这个方法在活动由不可见变为可见时调用,这时 Activity 已经可见了,但是还没有出现在前台,还不能和用户进行交互,我们可以理解为 Activity 已经有了,但我们还看不见

3)onResume

这里 Activity 已经可见了,可以和用户进行交互了,这时 Activity 处于栈顶,正在运行,这里要注意和 onStart 进行区分,可以理解为 onStart 和onResume 都表示 Activity 可见,但 onStart 的时候 Activity 还在后台,用户不可见,onResume 的时候在前台,用户可见

4)onPause

这个方法表示 Activity 正在停止,但还没有真正的停止,我们通常在这个方法中将一些消耗资源东西释放,可以存储一些关键的数据,但一定不能做耗时的操作,要不会意向下一个活动的使用

5)onStop

表示 Activity 即将停止,在 Activity 完全不可见得时候调用,可以做一些回收工作,也不能太耗时,这里要注意和 onPause 方法的区分,它和 onPause 方法的主要区别在于,如果新启动的方法是一个对话框式的活动,onPause 方法执行,onStop 方法不执行

6)onDestroy

表示 Activity 即将被销毁,对应于 onCreate 方法,这是 Acitivty 生命周期方法的最后一个回调方法,活动的状态将变为销毁状态

7)onRestart

这个方法在活动由停止状态变为运行状态时调用,这时候活动就是被重新启动了


上面这些都是一些理论的东西,下面我们就来真正的运行代码来看看 Activity 真正的执行情况


/**
 * 生命周期测试MainActivity
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState != null) {
            String data = savedInstanceState.getString("key");
        }
        Log.i(TAG, "MainActivity: onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "MainActivity: onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "MainActivity: onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "MainActivity: onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "MainActivity: onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "MainActivity: onDestroy");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "MainActivity: onRestart");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String data = "hello";
        outState.putString("key", data);
    }

    @Override
    public void onClick(View v) {
        Intent intent = new Intent(MainActivity.this,SecondActivity.class);
        startActivity(intent);
    }
}

这里我们创建了一个 MainActivity 并且重写了 Activity 生命周期的方法,这时候我们运行程序,在 Log 的控制台可以看到如下打印


MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume


这里正好验证了我们上面的理论,这时候我们用户可见,调用 onResume 方法

然后我们点击后退按钮,我们再来看一下控制台的打印内容


MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume
MainActivity: MainActivity: onPause
MainActivity: MainActivity: onStop
MainActivity: MainActivity: onDestroy


这时候一个 Activity 完整的生命周期就执行完毕了

接下来我们不点击后退键,我们点击 Home 键来看一下生命周期的情况


MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume
MainActivity: MainActivity: onPause
MainActivity: MainActivity: onStop


这里要注意 Activity 并没有去执行 onDestroy,这里 Activity 只是变成了不可见状态,并没有被销毁,我们再点击打开应用


MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume
MainActivity: MainActivity: onPause
MainActivity: MainActivity: onStop
MainActivity: MainActivity: onRestart
MainActivity: MainActivity: onStart

MainActivity: MainActivity: onResume


这里注意到应用并没有调用 onCreate 重新创建,而是只调用了 onRestart,onStart,onResume 方法

这里我们就把在正常情况下的一个 Activity 的生命周期情况介绍完毕,总结如下:


 

2. 活动(Activity)的状态


每个活动在其生命周期中最多可能会有 4 种状态


1)运行状态


当一个活动位于返回栈的栈顶时,这时活动就处于运行状态,系统最不愿意回收的就是出于运行状态的活动,因为这样会带来非常差的用户体验


2)暂停状态


       当一个活动不再处于栈顶位置,但仍然可见时,这时活动就进入了暂停状态,你可能会觉得,既然活动已经不在栈顶了,还怎么会可见呢?这是因为并不是每一个活动都会占满整个屏膜的,比如对话框形式的活动只会占用屏膜一部分的区域,处于暂停状态的活动任然是存活的,系统也不愿意去回收这种活动(因为它还是可见的),只有内存极低的情况下,系统才会去考虑回收这种活动


3)停止状态


       当一个活动不再处于栈顶位置,并且完全不可见的时候,就进入停止状态,系统任然会为这种活动保存相应的状态和成员变量,但是当其他地方需要内存时,处于停止状态的活动有可能会被系统回收


4)销毁状态


当一个活动从返回栈中移除后就变成了销毁状态,系统会最倾向于回收处于这种状态的活动,从而保持手机的内存充足


二、多个 Activity 交互的生命周期:


这里我们新建一个 SecondActivity 类,我们在 MainActivity 中设置一个点击按钮,用来跳到 SecondActivity,并且和 MainActivity 一样复写生命周期的方法如下

/**
 * 生命周期测试SecondActivity
 */

public class SecondActivity extends AppCompatActivity {

    private static final String TAG = "SecondActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Log.i(TAG, "SecondActivity: onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "SecondActivity: onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "SecondActivity: onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "SecondActivity: onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "SecondActivity: onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "SecondActivity: onDestroy");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "SecondActivity: onRestart");
    }
}

现在我们来看分析生命周期的运行情况:首先打开 MainActivity,控制台打印生命周期运行如下:

MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume


这时候我们再点击跳转按钮,控制台打印生命周期如下:

MainActivity: MainActivity: onPause
SecondActivity: SecondActivity: onCreate
SecondActivity: SecondActivity: onStart
SecondActivity: SecondActivity: onResume
MainActivity: MainActivity: onStop


这里我们思考如下内容

1)为什么要先调用 onPause 方法暂停当前显示的 MainActivity

2)为什么要等 SecondActivity 的 onCreate,onStart,onResume 方法执行完才执行 MainActivity的 onStop 方法,为什么不先执行当前 MainActivity的 onPause,onStop 方法呢?

分析如下:

在 MainActivity 打开 SecondActivity 的时候,会先执行 MainActivity 的 onPause 方法,然后执行 SecondActivity 的 onCreate、onStart、onResume 方法,完了再执行 MainActivity 的 onStop 方法,这里面还是有一种思想的,首先执行 MainActivity 的 onPause 方法是要关闭当前 MainActivity 的一些状态信息,如音频,视频等的状态,以免对新打开的 Activity 造成影响,试想我们正在听歌或看电影,这时候打进来一电话,如果我们不把当前的 Activity 先onPause 掉,会使一种怎样的体验,一边听歌,一遍打电话,不敢想象这样的场景,那么为什么又是在 MainActivity 执行完 onPause 而没有 onStop 的情况下就先执行 SecondActivity 的 onCreate,onStart,onResume 方法然后再执行 onStop 方法呢,这是因为考虑到如果在打开 SecondActivity 开启时发生 crash 的情况,这样如果 MainActivity 执行了 onStop 方法则会变为不可见状态,就会呈现出黑屏状态,用户什么都看不到。


三、横竖屏切换的时候 Acitivity 的生命周期:


打开 MainActivity,控制台打印情况如下:


MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume


这时候我们切换为横屏,看一下控制台的打印情况:


MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume
MainActivity: MainActivity: onPause
MainActivity: MainActivity: onStop
MainActivity: MainActivity: onDestroy
MainActivity: MainActivity: onCreate
MainActivity: MainActivity: onStart
MainActivity: MainActivity: onResume


还有就是在我们横竖屏切换的时候 Acitivity 的生命周期先是销毁掉然后会重新创建,所以我们展示的数据要在 onSaveInstanceState 方法中去保存数据,在 MainActivity 中添加如下代码就可以降临时数据进行保存:


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String data = "hello";
        outState.putString("key",data);
    }

这样数据就保存下来了,那么我们在哪里进行恢复呢?相信我们在一个地方经常看到这个 Bundle savedInstanceState,对,就是在我们的 onCreate 方法里面也有吧一个 Bundle 类型的参数,这个参数一般情况下都是 null,但是如果在活动被系统回收之前通过 onSaveInatanceState 方法来保存数据的话,这个参数就会带有之前所保存的所有数据,我们只需要通过如下方法取出:


  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState != null) {
            String data = savedInstanceState.getString("key");
        }
        Log.i(TAG, "MainActivity: onCreate");
    }

取值之后再做相应的操作就好了


四、如何启动系统的 Activity:


启动浏览器

@Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        Uri url = Uri.parse("https://www.baidu.com");
        intent.setData(url);
        startActivity(intent);
    }

启动相册:

@Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        startActivity(intent);
    }

发送短息:

 @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TEXT,"hello");
        startActivity(intent);
    }

启动电话界面:

 @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        Uri url = Uri.parse("tel:123456");
        intent.setData(url);
        startActivity(intent);
    }

如果想更多的去学习,可以去查看 Intent 相关的 API点击打开链接



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值