您的位置:首页 > 移动开发 > Android开发

android基础知识问答总结(一)__关于Activity

2017-09-03 20:41 344 查看
最近在看任玉刚的“Android开发艺术探索”,结合自己的最近面试情况和对一些问题的理解,来试着回答一些比较经典的问题吧。话不多说,试着去记录自己的想法吧:

典型的Activity生命周期

只是典型的分析,不涉及到异常的启动分析哦。

A. onCreate()

表示Activity正在被创建,它为Activity生命周期的第一个方法。在这个方法中我们可以做一个初始化工作,比如setContentView()和初始化一些数据的方法。

B.onRestart()

表示Activity正在重新被创建。正常的情况下,当Activity从不可见状态变为可见状态时,onRestart()将会被调用。Activity被压入栈底然后退到栈顶,onRestart()将会被调用。

C.onStart()

表示Activity正在被启动,此时Activity界面时可见的,但是无法获取焦点,也就是无法和用户进行交互。此时可以理解为可见的Activity,但是非前台Activity。

D.onResume()

表示Activity已经可见,且已经获取焦点,可以与用户进行交互了。

E.onPause()

表示Activity正在停止,此时Activity依然可见,但是已经失去焦点。正常情况下,紧接着onStop()就会被调用。在特殊情况下,此时快速返回Activity,那么onResume会被调用。可以做一些数据存储,停止动画等不太耗时的操作。因此只有新的Activity要显示时,必须等到旧的Activity执行完onPause和onStop。

F. onStop()

表示Activity即将停止,此时Activity已经不可见了,可以做一些稍微重量级的回收工作,同样不能太耗时。

G. onDestroy()

表示Activity即将被销毁,这是最后一个生命周期可回调的方法。在这里我们可以做一些回收工作和最终的资源释放。

方法对应问题

对于整个生命周期而言,onCreate和onDestroy是配对的,分别标识着Activity的创建与销毁,都只可能被调用一次;从Activity的可见性而言,onStart和onStop是配对的,随着用户的操作,这两个方法可能被调用很多次;对于Activity是否处于前台而言[换句话说是否对用户存在交互]onResume和onPause是配对的,随着用户的操作和设备的屏幕的点亮和熄灭,这两种方法也可能被调用多次。

既然存在配对,且onStart和onResume,onPause和onStop看起来差不多,在看起来接口有些重复的情况,我们是否可以只保留其中一对呢?答案是不能的,原因是这两对回调分别表示不同的意义,onStart和onStop是从Activity是否可见的这个角度来进行回调的,而onResume和onPause是从Activity是否位于前台的这个角度来回调的,除了这种区别,在实际使用中没有其他明显的区别。

Activity的启动模式

启动模式有四种,分别为standard,singleTop,singleTask,singleInstance四种模式。

standard模式

标准的启动模式,也是Android系统中默认的启动方式,每次启动一个Activity都会重新创建一个新的Activity,不考虑任务栈中是否存在这个实例。每一个新创建的Activity实例都会将生命周期方法统一走一遍:onCreate –> onCreate –> onResume。这是一种典型的多实例实现方式,一个任务栈中可以有多个实例共存,每一个实例也可以属于不同的任务栈。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。如果一个Activity A启动按standard模式启动了Activity B,那么B就会进入A所在的任务栈中。

singleTop模式

栈顶复用模式,如果你将要启动的Activity的实例正好位于任务栈的栈顶,那么此时Activity将不会被重建,只是会调用Activity的onNewIntent方法,通过此方法我们可以读取一些参数信息。按照所说的,Activity的onCreate,onStart由于Activity没有被重建,因此不会被调用。那么另一种情况是,如果将要的启动的Activity在对应的任务栈中没有该Activity的实例,或者存在Activity的实例,但是该实例不在任务栈顶,此时该Activity还是会像standard模式那样重建新的实例。举个例子,现在任务栈中存在A->B->C三个activity实例,假如要启动一个C的实例,由于C的启动模式时singleTop的,那么此时任务栈还是A->B->C;如果此时要启动B的实例,虽然任务栈中还存在B的实例,但其实例不在栈顶,那么B还是会创建,最终任务栈为A->B->C->B.

singleTask模式

任务栈内服务模式。这是一种单实例模式。在这种模式下,只要Activity在一个栈中存在,不管是否在栈顶、栈中还是栈底,Activity都不会被重建,只会调用其onNewIntent方法。具体点,当一个具有singleTask模式的Activity请求启动之后,就像Activity A,系统回首先查找是否存在A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建A的实例把A放到栈中。如果存在A所需的任务栈,这时候要看A是否在任务栈中存在实例,如果实例存在,那么系统就会把A调到栈顶并同时调用它的onNewIntent方法,如果实例不存在,就创建A的实例并把A压入栈中。

对于这个是否需要的任务栈,取决于将要启动的Activity的Context,如果这个Context是个Application,那么将会创建一个新的任务栈,如果是一个Activity,那么A将进入这个Activity的栈顶位置。举几个例子吧:

当前任务栈T1中情况为ABC,这是Activity D以singleTask模式请求启动,但是它需要的任务栈是T2,由于T2和D的实例都不存在,所以系统会先创建任务栈T2,然后再创建D的实例,然后压入T2中。

假如D需要的任务栈也是T1,由于T1已经存在,所以系统回直接创建D的实例,并将其入栈到T1的栈顶

假如D需要的任务栈还是T1,此时T1中情况为ADBC,根据复用原则,D将不会被重建,系统会将D切换到栈顶并调用其onNewIntent方法,同时singleTask还具有clearTop的效果,将会导致站内所在D上面的Activity全部出栈,所以T1中结果为AD.

singleInstance

功能和说singleTask类似,也是一种单实例模式,但它是一种加强型的singleTask模式,它除了singleTask的所有特性之外,还有另外一点就是此种模式下的Activity只能单独位于一个任务栈中,换句话说,比如Activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了。

那么对于singleTask和singleInstance,singleTask在JVM中可以因为不同的任务栈可以创建多个Activity的实例,但是singleInstance是位于一个单独唯一的任务栈,理论上Activity模式为singleInstance时,在JVM中最多只能存在一个实例。

Activity任务栈

什么是任务栈呢?这需要从一个参数说起:TaskAffinify,可以翻译为任务相关性。这个参数标识了一个activity所需要的任务栈的名字,默认情况下所有的Activity所需要的任务栈的名字都是应用的包名。当然我们可以为每个activity都单独制定TaskAffinity属性,属性值必须不能和包名相同,否则就相当于未指定。TaskAffinity主要和SingleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义。另外任务栈还分为前台任务栈和后台任务栈,后台任务栈中的activity位于暂停状态,可以通过切换将后台任务栈再次调到前台。

Activity部分Flags

Intent.FLAG_ACTIVITY_NEW_TASK

标记位的作用是为Activity指定”singleTask”启动模式,其效果和在XML中指定该启动模式相同.

Intent.FLAG_ACTIVITY_SINGLE_TOP

这个标记为的作用是Activity指定”singleTop”的启动模式,其效果和在XML中指定该启动模式相同。

Intent.FLAG_ACTIVITY_CLEAR_TOP

具有次标记位的Activity,当它启动时,在用一个任务栈中所有位于它上面的Activity都要出栈,该模式一般需要和Intent.FLAG_ACTIVITY_NEW_TASK相配合使用,在这种情况下,被启动的Activity的实例如果已经存在,那么系统就会调用它的onNewIntent方法;如果被启动的activity采用standard模式,那么它连同它之上的Activity都要出栈,系统会创建新的Activity实例并放入栈顶。

startActivity(new Intent(this,MainActivity.class).
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_CLEAR_TOP));


Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有这个标记的Activity不会出现在历史Activity列表中,当某些情况下我们不希望用户通过历史列表回到我们的Activity的时候这个标记比较有用。它等同于XML中指定Activity的属性android:excludeFromRecents=”true”;

好了,今天的总结就到这了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: