美文网首页四大组件
Android--探讨Activity的生命周期

Android--探讨Activity的生命周期

作者: windytouch | 来源:发表于2019-08-10 20:37 被阅读4次

    文章首发在个人公众号:追风栈Binary。希望共同交流和相互探讨。

    当我们在评价一个App的时候,经常会从流畅度、稳定性以及人性化这些角度去多维度的比较。一些操作流畅、页面精美的App即使没有什么大的实用意义,但我们都会选择多看几眼,相反的是,如果一个App启动慢,页面滑动卡顿,经常需要重新加载页面信息,那么毫无疑问,卸载是对它最后的仁慈。Android开发是通过Activity(活动)来完成与用户的交互,除了Activity的页面内容要丰富以外,也需要关注一个Activity是如何启动的,它的生命历程到底是怎么样的,我们才可以更好的优化应用程序。

    什么是Activity?

    简单的说,Activity就是应用程序的一个个页面,例如下面的两个应用程序的页面,制作的非常精美。

    Activity是Android应用程序重要的组成部分,它直接面向用户,接受用户的输入,并按照用户的意图来响应相应的操作。也正是因为它与用户直接交互,也就注定了Activity在应用程序中的重要性,就拿主页面来讲,如果连打开程序的主页面进行操作都会觉得卡顿不适的话,那用户很大可能就因此失去了了解这款App的兴趣,他可能就会选择不再打开或者直接卸载。所有的App都强调用户体验第一,就是这个道理。

    如何形象的理解应用程序中的Activity

    使用任何App的时候,我们可以感受得到页面仿佛是可以堆叠的,例如在主页面点击了一个登录按钮后就会跳转至登录详情页,登陆成功后就又会返回到我们的主页面。那么显示登录页面的时候,主页面去哪里了?为什么后面它又会原封不动的回来?

    实际情况与我们对于这种切换的认知是一致的,Activity可以堆叠,我们切换页面,使得不同的页面显示在当前的屏幕中,而之前的页面被系统管理了起来。以箱子和同等大小的木板来做类比,过程如下:

    • 箱子是一个管理Activity的机制,木板就是一个个的Activity

    • 我们永远只能看到箱子最上面的那块木板,意味着我们只能看到显示在屏幕当前的Activity

    • 我们点击进入新的页面,就好比往箱子里添加了一块新的木板,此时新木板处于最顶端,也正是我们看到的页面

    • 当我们返回上一个页面时,就好比把最上面的木板从箱子里抽取出来,我们回到了原来的界面

    • 当程序退出时,相当于木板都被抽取出来,箱子此时是空的。

    Android使用Task来管理活动,一个Task就是一组Activity的集合,而上面的箱子,在Android中被称为返回栈,栈的特性就是和箱子一样,先进来的反而后出去。这也和我们使用App的感受一致,如果从主页面点开另一个页面,然后从另一个页面点开再另一个页面...,到后面要返回到主页面时,就不得不一直按返回键,直到最后达到主页面。其实这些操作,就是Activity不断入栈和出栈的过程。

    Activity生命周期中有哪些方法?

    在新建一个Android Studio工程的时候,选择Empty Activity后,会自动的创建一个MainActivity,并且会自动的在AndroidManifest文件中声明该Activity为启动页面:

    <activity android:name=".MainActivity">
     <intent-filter>
     <action android:name="android.intent.action.MAIN" />
     <category android:name="android.intent.category.LAUNCHER" />
     </intent-filter>
    </activity></pre>
    

    也就是说,点击应用图标后,首先映入眼帘的就是这个界面(当然这个指的是主页面,而并不是指启动页面)。可以指定任何程序中的Activity作为程序的主页面,但是需要在AndroidManifest文件中进行<intent-filter>的相关配置。

    Android对Activity生命周期定义了七种方法,分别如下:

    • onCreate():指的是Android系统初次创建这个Activity时调用的方法,这是一个必须实现的方法,我们需要在里面设置setContentView()方法,并且还要进行一系列控件的绑定,onCreate()接收一个savedInstanceState的参数,这个参数的意思是保存Activity先前状态的信息,但是如果是第一次创建,那么saveInstanceState中就没有任何的信息。

    • onStart():指的是系统将这个Activity变为用户可见,这个方法执行的十分快速,紧接着就是onResume()

    • onResume(): 指的是Activity准备好与用户进行交互了,此时它处于返回栈的栈顶,是用户直接接触的对象

    • onPause(): 指的是当Activity不再是处于栈顶,但它可能还是会对用户可见的时候,一般指的是当前页面突然弹出一个对话框,此时Activity就是处于onPause()状态

    • onStop(): 指的是当Activity完全不可见的时候,例如主页面跳转到登录页面,那么此时主页面就是处于onStop状态

    • onDestroy(): 指的是Activity将要被销毁了,例如在主页面按返回键回到桌面时,会调用此方法

    • onRestart(): 当ActivityonStop()状态到onStart()状态下切换时调用,例如从登录页面返回到主页面

    本来打算自己画一个流程图,但是Android指南上的流程图太经典了,绘制的很详细,所以直接把那幅图搬到这里来。


    还可以看出,除了onRestart(),其余的六种方法都是配对出现的,onCreate()对应onDestroy()onStart()对应onStop()onResume()对应onPause()

    Activity的生命周期示例

    文章的重点是讨论Activity的生命周期,也就是要探讨程序启动、页面跳转、弹出对话框、程序退出等场景时Activity的行为,具体分析如下两个方面

    • Activity在这些场景下,它做了哪些事情

    • Activity在这些场景下,它分别处于什么状态

    为了更直观的展示,建立了一个ActivityLifeCycleDemo的示例,很多时候Android Studio默认生成了必须重写的onCreate()方法,而其他方法则默认继承父类方法,导致我们无法查看生命周期状态,这个例子重写了继承的方法,加入了Log以便打印信息

    跳转逻辑:MainActivity(启动主页面)、点击"跳转至正常的Activity"跳转到"这是正常的Activity"、点击"跳转至对话框Activity"跳转到"这是对话框的Activity"


    // MainActivity代码,重写了继承父类的一些方法
    @Override
    protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     Log.d(TAG, "1: 我在onCreate()方法");
     setContentView(R.layout.activity_main);
     initView();
    }
    ​
    private void initView(){
     Button turnToNormal = findViewById(R.id.start_normal);
     Button turnToDialog = findViewById(R.id.start_dialog);
    ​
     turnToNormal.setOnClickListener(this);
     turnToDialog.setOnClickListener(this);
    }
    ​
    @Override
    public void onClick(View view) {
     switch (view.getId()){
     case R.id.start_normal:
     Intent normalIntent = new Intent(this, NormalActivity.class);
     startActivity(normalIntent);
     break;
     case R.id.start_dialog:
     Intent dialogIntent = new Intent(this, DialogActivity.class);
     startActivity(dialogIntent);
     break;
     default:
     break;
     }
    }
    ​
    @Override
    protected void onStart() {
     super.onStart();
     Log.d(TAG, "2: 我在onStart()方法");
    }
    ​
    @Override
    protected void onResume() {
     super.onResume();
     Log.d(TAG, "3: 我在onResume()方法");
    }
    ​
    @Override
    protected void onPause() {
     super.onPause();
     Log.d(TAG, "4: 我在onPause()方法");
    }
    ​
    @Override
    protected void onStop() {
     super.onStop();
     Log.d(TAG, "5: 我在onStop()方法");
    }
    ​
    @Override
    protected void onDestroy() {
     super.onDestroy();
     Log.d(TAG, "6: 我在onDestroy()方法");
    }
    ​
    @Override
    protected void onRestart() {
     super.onRestart();
     Log.d(TAG, "7: 我在onRestart()方法");
    }
    

    1.当点开程序图标,MainActivity中发生了什么?

    点击程序图标,进入MainActivity,显示主页面。由于打印了Log日志,所以可以使用Logcat查看这些输出信息。

    可以看到Logcat打印出了三条信息,并且调用方法的顺序依次是onCreate()onStart()onResume()。这说明当系统第一次启动该应用的时候,会通过onCreate方法来创建一个MainActivity的实例,完成控件和事件的绑定,例如上面程序中的findViewById()onClick()这些方法。并随后调用onStart()onResume()的方法,这些方法的执行很快,从时间上看,两个方法几近是同一时刻调用的。完成这三个方法后,主页面显示在用户面前,并一直处于onResume状态。

    2.从MainActivity切换到正常的Activity,会发生什么?

    点击主页面的跳转至正常的Activity按钮,程序会跳转到另外一个界面上:

    查看Logcat的输出信息

    可以看出,从MainActivity跳转至另外一个Activity时,MainActivity会依次调用onPause()onStop()的方法,正如指南中所说,当Activity完全不可见时,调用onStop()的方法,这一点在示例中得到了验证。现在MainActivity不再处于栈顶,处于栈顶的是这个正常的Activity

    3.从正常的Activity返回到主页面会调用什么?

    现在我们要返回到MainActivity,通过按返回键就可以实现:

    查看Logcat的输出信息

    注意,从完全不可见恢复到完全可见的状态,是通过调用onRestart()方法来实现的,然后再依次调用onStart()onResume()方法,重新获得焦点,现在MainActivity又回到了栈顶了。

    4.从MainActivity到对话框Activity,又会发生什么?

    我们现在从MainActivity出发,点击跳转至对话框Activity按钮,跳至对话框页面。但要注意,对话框是一种局部覆盖MainActivity的页面,它不会让MainActivity完全消失。

    查看Logcat,看看这个过程与上一个过程到底有何不同。

    这个调用过程并不像是上面过程一样,这里的MainActivity只调用了onPause()方法,而没有继续调用onStop()方法,这说明MainActivity并没有完全消失,从直观的角度来看,我们仍然可以看得到对话框下的MainActivity,只不过是被对话框页面蒙上了一层灰色。

    5.从对话框页面返回MainActivity,会发生什么?

    现在从对话框页面点击返回键回到主页面

    查看Logcat的输出信息

    从对话框跳回至MainActivityMainActivity直接调用了onResume()方法,这一步也没有调用onRestart()方法。

    6.在MainActivity上按返回键退出,会发生什么?

    测试在主页面上直接按返回键,返回到手机桌面上,这一步过程中MainActivity会调用哪些方法。依旧查看Logcat,查看输出信息:

    退出应用时,程序相当于被关闭了。MainActivity依次调用onPause()onStop()之后,会调用onDestroy()方法来销毁自身。那如果不是按返回键,而是按Home键回到桌面上,那会有区别吗?

    7. 在MainActivity上按HOME键回到桌面,会发生什么?

    MainActivity上直接按Home键,也同样会回到桌面上,那么此时MainActivity会把自身销毁掉吗?查看Logcat的输出结果,就会知道答案。

    Logcat的输出结果表明,点按Home键回到桌面上时,MainActivity并不会调用onDestroy()的方法,反而是和MainActivity被另一个页面覆盖的结果相同。但是这种方式回到桌面,那么程序很有可能会被后台管理程序回收,这就是为什么有时我们打开微信后又回到桌面上,过一段时间打开微信需要重新进入的原因。

    至此,Activity生命周期的讨论就可以先告一段落了。

    如何快速的记住这些方法?

    都说把它们全部理解了,就顺便记下来了。但我觉得,可能先记下来,再后面遇到了慢慢理解也不迟。七个方法按一个Activity创建到销毁的顺序来,会好记很多。

    我个人喜欢用通俗的方式来记忆,比如说这七个方法,除去特殊的onStart()外,按照每个方法的大写字母来顺序排列,那就是C-S-R-P-S-D,其中C-S就记忆成反恐精英R-P记忆成人品S-D记忆成SD卡,最后只需要单独记忆一个onStart()就可以了。

    相关文章

      网友评论

        本文标题:Android--探讨Activity的生命周期

        本文链接:https://www.haomeiwen.com/subject/oskdjctx.html