4 活动生命周期:活动的一生

1.活动是所有Android应用的基础

1.1 活动如何工作

1.1.1 应用是一个由活动、布局和其他资源组成的集合。

其中一个活动是应用的主活动。

1.1.2 每个应用都在自己的进程中运行。

每个应用都在自己的进程中运行。

1.1.3 Android虚拟机--ART(AndroidRunTime)

Android应用需要在功耗低、内存小的设备上运行。

Java应用要占用大量内存,而且由于Java应用在自己的Java虚拟机 (Java VirtualMachine,JVM)中运行,如果在低功耗的机器上运行,会花很长时间启动。Android可以解决这个问题,它并不使用JVM来运行应用。实际上,Android会用一个完全不同的虚拟机,叫做Android运行时(Android runtime,ART)

Android运行时(Android runtime,ART))是Android设备上运行已编译代码的系统。ART设计为可以在低功耗的小设备上快速、高效地运行编译的Android应用。

ART与JVM完全不同

Java问世已经很长时间,已编译的Java程序几乎都在Oracle的Java虚拟机(Java Virtual Machine,JVM)上运行。JVM会模拟一个CPU芯片读取已编译的.class文件,其中包含JVM机器代码指令,这称为字节码。传统做法是将.java源文件编译为.class文件。然后使用JVM解释器运行这些.class文件。

ART则完全不同。编译一个Android应用时,开始是一样的。你要编写.java源文件,把它们编译为.class文件,不过然后会有一个名为dx的工具将这组.class文件(或.jar归档文件)转换为一个名为classes.dex的文件

 这个classes.dex文件也包含字节码,不过这与.class文件中的字节码不同。.dex字节码由一个完全不同的虚拟处理器处理,这个虚拟处理器名为Dalvik。实际上,dex就代表Dalvik Executable。

Dalvik处理器与JVM有些类似。JVM和Dalvik都是虚拟处理器,而且它们都要模拟芯片。不过Oracle JVM是一个基于堆栈的处理器,而Dalvik是一个基于寄存器的处理器。有些人认为,基于寄存器的处理器处理的代码可以优化得更小,并能更快地运行。dx工具将一组不同的类文件转换为一个classes.dex文件,使得已编译应用的规模更小,因为它能去除多个.class文件中可能出现的大量重复的符号

然后这个classes.dex文件与另外一组资源和数据文件一同压缩到一个ZIP文件,这称为一个应用包,或APK文件.apk文件是最终安装在Android设备上的已编译应用。最后就是要把这个文件上传到Google Play Store。

Android如何运行APK文件

APK文件就是一个ZIP压缩的归档文件。安装在Android设备上时,APK文件存储在一个名为/datalappl的目录中,然后会从这个归档文件解压缩得到classes.dex文件。

从APK归档文件中解压缩得到classes.dex文件后,它会转换为一个原生库。Dalvik字节码成为原生机器码指令,可以直接由设备的CPU运行。然后再将这个已编译的库存储在/dataldalvik-cache目录。Android只需要在第一次运行应用时完成这个原生编译步骤。在此之后,Android设备可以直接加载和运行这个原生库。

Android就是一个特殊版本的Linux操作系统,正常情况下Linux无法运行Android应用。正是因为这个原因,每个Android设备都会运行一个名为Zygote的进程。Zygote就像一个已经启动并运行的Android进程。告诉Android启动一个新Android应用时,Zygote会创建自己的一个分支版本。分支进程就是进程在内存中的另一个副本。Linux可以很快地创建分支进程,所以通过创建Zygote进程的分支进程,然后加载原生库,可以非常快地加载Android应用。

性能和大小

与通常运行Java代码的机器相比,Android设备的功耗和存储容量都要小得多。ART使用的.dex文件通常也比等价的.class文件小。Oracle JVM可以使用即时编译(JIT compilation)来编译部分代码,这意味着JVM可以在运行代码的同时将Java字节码转换为机器码。这对于运行很长时间的应用是很合适的,比如应用服务器,但是Android应用可能会频繁地启动和停止。通过将所有Dalvik字节码提前编译为一个原生库,ART可以确保只需要编译一次代码。

最后,在低功耗的设备上,Oracle Java运行时环境可能要花费很长时间才能启动。通过使用Zygote进程,Android可以更快速地启动和运行应用。Zygote进程还可以使用共享内存安全地执行所有Dalvik进程共有的代码。

安全性

Android设备可能会运行很多不同开发人员开发的代码,有一点很重要;每个应用都与所有其他应用完全隔离。如果没有这种隔离,一个应用就有可能破坏设备上其他应用的安全。为了确保应用是隔离的,Android会在单独的进程中运行各个应用,而且有一个自动生成的用户帐户。利用Linux提供的操作系统级安全,可以保证应用是隔离的。如果使用Oracle Java运行时,每个进程都需要自己的Java进程,这会大大增加运行多个应用所需的内存。
 

1.1.4 startActivity()传入一个意图启动另一个应用中的活动

Android系统知道已安装的所有应用和它们的活动,可以使用意图启动正确的活动。

1.1.5  需要启动一个活动时,Andorid会检查是否已经有一个进程在运行这个应用

如果存在这样一个进程,Android就会在该进程中运行这个活动。如果不存在这样的进程,Android将创建一个进程。

1.1.6 Andorid启动一个活动时,会调用它的onCreate()方法

只要创建活动就会运行onCreate()

2.从生到死:活动的状态

Android创建和撤销活动时,这个活动会从启动状态进入运行状态,然后再被撤销。

活动的主状态就是运行活动状态。如果一个活动在屏幕前台,而且得到了焦点,用户可以与之交互,这个活动就处于运行状态。活动一生的大部分时间都处于这个状态。活动启动后就开始运行,寿终正寝时,活动会被撤销


活动在屏幕前台时处于运行状态。

第一次创建活动时会调用onCreate(),通常的活动设置工作都在这里完成。

活动撤销之前会调onDestroy()。

活动从启动状态变到撤销状态时,会触发几个关键的活动生命周期方法:onCreate()和onDestroy()方法。它们是活动继承得到的生命周期方法,如果需要,可以覆盖这些方法。

活动启动之后就会立即调用oncreate()方法。活动的所有设置工作就在这个方法中完成,如调用setContentview()。一般都要覆盖这个方法。如果没有覆盖,可能就无法告诉Android你的活动要使用哪个布局。

onDestroy()方法是活动撤销前最后调用的方法。很多情况下有可能会撤销活动,例如,活动完成,或者由于设备配置发生变化导致活动重新创建,也可能是Android决定撤销这个活动以节省空间。

3.活动生命周期:从创建到撤销

3.1 活动生命周期中的onCreate()和onDestory()方法

 上图中的5个阶段,分别进行的活动(主要围绕onCreate()和onDestory()):

阶段主要活动描述
1活动启动创建了活动对象,并运行它的构造方法
2活动启动之后立即运行onCreate()方法所有初始化代码都放在onCreate()方法中,因为活动启东支行但在真正开始运行之前总会调用这个方法
3活动在前台可见而且用户可以与之交互时,这个活动就处于运行状态活动一生的大部分时间都在这里度过
4活动撤销之前运行onDestroy()方法onDestory()方法允许你完成最后的所有清理工作,如释放资源
5onDestory()方法运行之后,活动被撤销这个活动不再存在

3.2 活动继承了生命周期方法

这本书前面已经看到,活动扩展了android.app.Activity类。正是因为这个类,活动才可以访问Android生命周期方法:

3.3 处理配置变化--保存当前状态

问题: 用户旋转屏幕时我们的应用出问题了。活动被撤销然后重新创建,这说明活动使用的局部变量会丢失。那么如何解决这个问题呢?如何处理设备配置的变化,如屏幕方向的改变?

有两个解决办法,一般使用 第二种:保存当前状态

处理配置变化还有一种更好的方法,这也是最常使用的方法,即保存活动的当前状态,然后在活动的onCreate()方法中重新恢复这个状态

要保存活动的当前状态,需要实现onsaveInstancestate()方法。onSaveInstanceState()方法将在活动撤销之前调用,这说明,如果你想保留某些值,在这些值丢失之前你还有一个机会保存它们。

onsaveInstancestate()方法有一个参数,即Bundle。利用Bundle可以把不同类型的数据收集到一个对象中:

onSavelnstanceState()方法在onDestroy()之前调用。这会提供一个机会,允许你在活动撤销之前保存活动的状态。

 onCreate()方法得到作为参数传入的Bundle。这说明,如果把running和seconds变量的值增加到Bundle中,onCreate()方法会在活动重新创建时得到这些值。为此可以使用Bundle的方法将名/值对增加到Bundle。这些方法的形式如下:

 bundle是Bundle的名,*是你想要保存的值的类型,name和value是数据的名和值。

前面我们说过,onCreate()方法有一个参数Bundle。如果这个活动是从头创建的,这个参数就是null。不过,如果这个活动是重新创建的,之前已经调用过onSaveInstancestate(),就会把onSaveInstanceState()使用的Bundle对象传递给活动.可以通过以下形式的方法从Bundle得到值:

这里bundle是Bundle的名,*是你想要得到的值的类型,name是上一页指定的名/值对的名。

3.4 活动生命周期:可见生命期

幸运的是,通过使用正确的生命周期方法,可以很容易地处理与活动可见性相关的动作。onCreate()方法和onDestroy()方法用来处理活动的整个生命周期,除了这两个方法,另外还有一些处理活动可见性的生命周期方法。

3个关键的生命周期方法可以用来处理活动对用户可见或不可见时的工作。这些方法分别是onStart()、onstop()onRestart()。就像onCreate()和onDestroy()一样,这些方法也是活动从Android Activity类继承的。

活动对用户可见时会调用onStart()

活动不再对用户可见时会调用onStop()。这可能是因为它完全被在它上面显示的另一个活动隐藏,或者因为这个活动将被撤销。如果由于活动将被撤销而调用onstop(),调用onstop ()之前就会调用onSaveInstancestate()。

如果活动不可见,在它重置为可见之前,会调用onRestart()

如果一个活动被另一个活动完全隐藏,对用户不可见,它就处于停止状态。这个活动仍然存在于后台,还维护着所有状态信息。

阶段主要内容描述
1活动启动,并运行onCreate()方法运行onCreate()方法中的所有活动初始化代码。此时活动还不可见,因为没有调用onStart()方法
2onStart()方法在onCreate()方法之后运行。活动可见之前会调用这个方法运行onStart()方法之后,用户将在屏幕上看到这个活动
3活动不再对用户可见是会运行onStop()方法运行onStop()方法之后,活动不再可见
4如果活动再次对用户可见,会调用onRestart()方法,然后调用onStart()如果活动在不可见和可见之间返回地来回切换,它会多次经过这个循环。
5最后,撤销活动在onDestory()之前会调用onStop()方法,不过如果设备的内存很低,则有可能跳过这个调用。

需要注意的是,覆盖一个活动生命周期方法时,需要调用相应的超类方法。如果没有做到这一点,将会得到一个异常

3.5 活动生命周期:前台生命周期

还有一种情况:尽管活动可见,但是并没有得到焦点

如果活动可见,但没有得到焦点,活动会暂停。如果另一个活动出现在这个活动之上,而且它不是全屏显示,或者是透明的,这种情况下尽管你的活动是可见的,但是并没有得到焦点。在它上面的活动得到了焦点,不过下面的活动仍然可见,所以会暂停

在3.4 的基础上,又增加了onResume()和onPause()方法:

 

阶段主要内容描述
1活动启动,运行onCreate()和onStart()方法活动是可见的,不过还没得到焦点
2onResume()方法在onStart()方法之后运行。活动将要移至前台时会调用这个方法运行OnResume()方法之后,这个活动得到了焦点,用户可以与它交互。
3活动不再处于前台时会运行onPause()方法运行onPause()方法后,活动仍然可见,但是没有得到焦点
4如果活动再次移入前台,会调用onResume()方法如果活动反复地失去和再次得到焦点,活动可能会多次进入这个循环。
5如果活动不再对用户可见,会调用onStop()方法运行onStop()方法后,活动不再可见
6如果活动再次对用户可见,会调用onRestart()方法,接下来会调用onStart()和onResume()方法活动可能会多次进入这个循环
7最后 ,活动会被撤销活动从运行状态移至撤销状态时,在活动撤销前会调用onPause()方法。通常还会调用onStop()方法。

3.6 生命周期方法快速指南

方法何时调用下一个方法
onCreate()活动第一次创建时。用于正常的静态设置,如创建视图。它还可以传递一个Bundle,提供之前保存的活动状态。onStart()
onRestart()活动已经停止,再次启动之前回调用这个方法。onStart()
onStart()活动变得可见。如果活动进入前台,接下来会调用onResume(),如果活动变得不可见,接下来会调用onStop()onResume()或onStop()
onResume()活动在前台时onPause()
onPause()由于另一个活动恢复运行而导致这个活动不再在前台。这个方法完成之前,不会继续运行下一个活动,所以这个方法中的所有代码需要很快地运行。如果活动返回到前台,接下来会调用onResume(),如果活动变得不可见,接下来则会调用onstop()。onResume()或onStop()
onStop()活动不再可见时。这可能是因为另一个活动把它盖住了,或者是因为这个活动被撤销。如果活动再次可见,接下来会调用onRestart(),或者如果活动将被撤销,则会调用onDestroy()。
 
onRestart()或onDestory()
onDestory()活动将被撤销,或者活动将要完成


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部