View体系之四大组件——Activity

版权声明:本文为博主原创文章,转载请说明出处 https://blog.csdn.net/ckq5254/article/details/79950792
View体系之四大组件——Activity
首先在讲解Activity之前,我们先提出几个问题,之后一一解答。
(1)Activity的作用是什么?
(2)对Activity中的各个生命周期的理解
(3)对Activity的启动模式的理解
(4)区别Activity和AppcompatActivity
(5)理解Fragment以及其生命周期
(6)关于finish方法的理解
(7)常见场景Activity的生命周期分析
好了,现在开始我们的正题。

一、Activity生命周期
        Activity是Android提供的四大组件之一,通常用于为用户呈现界面。(解决问题(1))
        1、Activity的生命状态
             如下图 1:

图  1


        很多人对Activity中生命周期方法和生命周期状态有一定的误解,这里我们首先要把这个概念搞明白。
生命周期方法依次是:onCreate()-->onStart()-->onResume()-->onPause()-->onnStop()-->onStop()
生命周期状态为:created-->started-->resumed-->paused-->stoped--desptoryed
那么你可能要问了,他们之间有什么关系呢?
其实从图1中你也可以看出来,比如说一个Activity在执行完生命周期方法onCreate()方法后则进入created状态。


        Activity的状态从持续时间长短上分为瞬态和静态两种。那么哪些属于静态,哪些又属于瞬态?
瞬态:created,started,destoryed,Activity到达某一个瞬态后会立即执行后面的方法,进入其他状态。
静态:resumed,paused,stoped,根据实际场景,Activity可能会停留这某一个静态
        原因是,在生命周期的方法中,会依次执行onCreate()、onStart(),onResume(),执行完onResume()方法后,此时Activity可见并可获得焦点,处于resumed状态。
 而如果被其他Activity遮挡但是仍然可见,则会执行onPause()进入paused状态,如果此时跳转到另一个Activity后,则会执行onPause()、onStop()方法处于stoped状态。
如果退出应用,那么此时Activity执行onDestory()执行销毁。具体可以参考下图  2:
Activity对应的状态有如下:

图  2
2、生命周期具体分析


生命周期方法
说明
onCreate()
在这一方法中,会创建Activity的实例,此时调用finish()方法会立即执行onDestory()
onStart()
此时Activity已经可见但是无法获得焦点
onResume()
此时可见有焦点
onPause()
可见但是无焦点
onStop()
此时无焦点也不可见,通常考虑在这里释放资源
onDestory()
销毁对应的Activity对象
onRestart()
通常用于从onStop重新进入onResum时,或者通过onNewIntent()重新复用Activity时

注意:
         特别注意,在极端情况下,系统可能会终止应用进程,此时则不会调用Acitivity的onDestory()但是一定会调用onStop(),因此在onStop()中需要及时释放那些需要释放的资源。(比如低内存直接杀死进程)(具体看源码中Activity中的注解)
        Activity在Stop状态时,Activity实例对象驻留在内存中,在重新调用onResume()后,不需要重新初始化,(这里指的是Activity对象不需要重新初始化,因此也不需要重新走onCreate();此外在onCreate或者onstart()或者onResume中初始化的组件,并且在onStop中没有进行销毁操作的,也不需要初始化,此外,系统还会跟踪这些view的当前状态,比如已经输入过内容的EditText,重新onResume后内容仍然在)。
        对于非正常终止Activity的问题,需要注意,系统会保留这种情况下的Activity,因此可以在
            Activity在正常应用行为下会执行销毁,比如按返回或者调用finish()。此外Activity被停止或者长期未使用或者前台Activity需要更多资源时也会关闭后台进程来恢复内存此时也会销毁Activity。
            对于非正常应用行为销毁Activity,系统会记住其存在,此时可以使用Bundle对象来存储键值对数据从而重新创建Acitvity实例。以下为常见的两种方法
            (1)使用onSaveInstanceState(Bundle outState)
                      首先覆写onSaveInstanceState()方法,并传入我们要保存的值,如下:
            
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
String string = "activity 被系统回收了怎么办?";
outState.putString("Activity", string);
}

然后在onCreate中重新初始化组件时,在onCreate()方法中判断Bundle是否为空,从而取出对应的键值对。

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String oldString = savedInstanceState.getString("Activity");
}
}
     说明:在系统由于资源问题回收Activity实例时,并不一定会回调此方法,这里需要注意这个不一定。假设会回调,那么也是在当前Activity的onStop()方法以前。
      哪些情况一定会回调此方法:
  • 用户按home键
  • 从最近的应用切换过来
  • 按关机键关闭屏幕显示
  • 启动另一个Activity
  • 横竖屏切换时(如果没有在activity中设置configuration属性)
(2)使用onRestoreInstanceState()
            做法和onSaveInstanceState()方法基本相同,只是此方法只有在系统由于资源问题回收了Activity并重新恢复其实例对象或者横竖屏切换时才会调用


二、关于finish的理解
      finish方法是用来完成从Activity栈移除当前Activity的方法(这需要注意,并不是销毁当前Activity)。那么在一个Activity的不同生命周期下调用finish又有什么不同呢?
  1.在onCreate()方法中调用finish()
     在onCreate()中,调用finish方法,出现闪退,无法正常显示Activity界面
      生命周期为:onCreate、onDestroy。

  2.在onStart()方法中调用finish()
    在onStart()方法中,调用finish,会出现闪退,无法正常显示Activity界面。
   生命周期为:onCreate、onStart、onStop、onDestroy。

 3.在onResume()方法中调用finish()
    在oResume方法中,调用finish,会出现闪退
    生命周期为:onCreate、onStart、onResume、onPause、onStop、onDestroy。

 4.在onPause、onStop、onDestroy中调用finish
    在onPause、onStop、onDestroy中,调用finish,显示正常然后退出。
    生命周期为:onCreate、onStart、onResume、onPause、onStop、onDestroy。
        
三、在不同场景下Activity的生命周期调用 (在分析不同场景 下的生命周期方法调用时,根本在于掌握各个生命周期的特征,比如是否可见,是否可获得焦点)
        1、前台到后台,后台到前台(也就是Home键)
              onCreate->onStart->onResume->onPause->onStop->onRestart()->onStart->onResume
        2、当有一个Dialog弹出时,生命周期如何变化
                这需要区分是什么Dialog,如果是 AlertDialog,因为在实例化时是调用AlertDialog.Builder builder=new AlertDialog.Builder(this),这里的this就是当前的Activity实例,因此在弹出dialog时代表我们的Activity其实仍然处于交互状态,仍然是当前Activty可见并获得焦点,因此仍然是可见状态
                如果是Dialog式的Activity,那么相当于另起一个Activity,此时会调用onPause()方法
        3、横屏竖屏时生命周期切换
              具体可能与手机有关,在没有设置android:configChanges=”orientation|keyboardHidden|screenSize”,此时,横屏切竖屏或者竖屏切换横屏,生命周期onCreate->onStart->onResume->onPause->onStop->onDestory->onCreate->onStart->onResume,也就是说在横竖屏切换后,相当与销毁了当前的Activity,又启动了另外的一个Activity。
                设置了android:configChanges=”orientation|keyboardHidden|screenSize”后,切换屏幕不会执行生命周期
                原因:设置了configChanges参数,则在这些参数发生改变时,也不会重新创建Activity
        4、下拉状态栏是不是影响activity的生命周期?
                不会

四、启动模式与Intent的flag分析
        在了解启动模式以前,首先需要我们知道两个概念——Task和Back Stack

        1、Task和Back Stack    
                Task,翻译过来就是任务,指的是Activity的集合或者容器,而这个集合/容器呢,则是使用一个栈来进行管理的,这个栈称为Back Stack。通常来说中Activity的顺序是按照他们被打开的顺序来依次存放的,遵循后进先出的原则,但是也绝对,比如之后我们设置的启动模式,可能就会打破这种约束。
                那么为什么要使用栈的结构来保存Activity的集合呢?
                实际上一个应用包含很多个Activity,而每个Activity都对应了特定的功能,用于给用户操作,而不同的Acitivity可以通过Intent来互相启动。比如说从点击一个app图标开始,首先是启动的Activity,然后主界面Activity,然后点解头像,开始注册Activity,然后登录Activity。如下图 1:

图 1

        在这一过程中该应用一共产生了四个Activity实例,那么如果此时我按返回,那么会回到注册界面,再按返回,会回到主界面,再按返回会回到启动界面。很明显这里符合后进先出的概念(这里其实是逆推,怎么说呢,整体来说应该是这种结构简单,符合设计需求,便于管理)
    2、启动模式launchMode分析
            这里我们主要针对启动的是同一个应用的Activity还是不同应用的Activity来具体分析。     
(1)standard(默认启动模式)
          即每次启动一个Activity都会创建一个新的Activity实例,然后加入到Task中。
         同一应用:每次启动一个Activity都会创建一个新的Activity实例,然后加入到当前应用的Task中。
         不同应用:在Android 5.0以前,会创建新的实例并加入到启动该Activity的应用的Task中;在5.0以后,会新建一个Activity的实例,并且新建一个Task,然后加入。

(2)singleTop(栈顶复用模式)
           同一应用:每次启动一个Activity会判断当前Task栈顶的Activity是不是我们将要启动的Activity,如果是,则调用onNewIntent()重新启动,否则创建新的实例并加入当前应用的Task。
           不同应用:在5.0以前,由于会加入到启动该Activity的应用的Task中,因此首先判断栈顶是不是我们需要的,如果不是则重新创建实例,并加入到当前应用的Task中。5.0以后,会直接新建实例然后加入到新建的Task中。

(3)singleTask(栈内复用模式)
           同一应用:如果该栈中有其实例(没有栈顶的限制条件),则不会重新创建实例,而是将之前的Activity移除,将其置于栈顶。
          不同应用:判断是否存在另一个应用的Task,如果不存在,创建,然后新建Activity实例,加入到新建的Task中;如果存在,判断是否有对应实例,没有,则新建实例加入,有,则移除它上面其他实例,使它位于栈顶。
              
(4)SingleInstance(单一实例模式)
          即整个手机系统里只有一个实例存在。(不论在哪个Task中)
           对于声明为SingleInstance的Activity,它所在的栈中不会再放入Activity,也就是这个Task中只有它一个实例。而通过它启动的Activity也会放入其他Task中,因此可以保持单一实例。

2、Intent的flag
      这里介绍我们常用的Flags。
    (1) FLAG_ACTIVITY_NEW_TASK(每启动一个Activity就创建一个Task)
            这里无论是否跨进程,每次启动一个Activity,都会新建一个Task,同时新建Activity实例,然后放入Task栈中。
            这里注意它不同与Sing了Instance单一实例模式
            singleInstance会在Activity不存在时,新建一个Task并放入,但是再次启动时就不会重复创建,而是保持单一实例状态。
            NEW_TASK在每次启动时不论是否已经存在实例,都将该Activity放入一个新建的Task


      (2)  FLAG_ACITVITY-SINGLE_TOP
                  同LaunchMode中的singleTop


      (3)   FLAG_ACTIVITY_CLEAR_TOP
                 同LaunchMode的singleTask

      3、 关于Task栈的后台清理问题
            默认情况下, 一个Task在后台过了很长时间后,系统会将该Task中除最底层的Activity清除掉,在重新回到前台后,最底层的Activity会得到恢复。但是我们可以改变这种默认的状态,即通过在Manifest中的<activity>属性中进行设置。
            (1)alwaysRetainTaskState    总是保持Task状态
                    设置为True后,即使Task后台一段时间该Task仍然会保留。
          (2)clearTaskOnLaunch 
                     该Task进入后台后,会立即清理该Activity以上的所有Activity
            (3)finishOnTaskLaunch
                    该Task处于后台后,这个Activity就会被清除
                    
                    



阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页