Activity
一、Activity的四种状态
- running:当前activity处于运行状态,当前activity获取了焦点。
- paused:当前activity处于暂停状态,失去焦点,但是并没有被摧毁。
- stopped: 和paused状态相似,但是activity完全不可见。
- killed:activity被销毁,内存、成员变量、状态信息一并被销毁。
二、activity的生命周期
image.pnghttps://www.jianshu.com/p/f9da7ecded20?utm_campaign=maleskine&utm_content=note&utm_medium=writer_share&utm_source=weibo
Activity启动–>onCreate()–>onStart()–>onResume()
点击home键回到桌面–>onPause()–>onStop()
再次回到原Activity时–>onRestart()–>onStart()–>onResume()
退出当前Activity时–>onPause()–>onStop()–>onDestroy()
onCreate():
表示Activity正在被创建,这是Activity生命周期的第一个方法。通常我们程序员要在此函数中做初始化的工作,比如:绑定布局,控件,初始化数据等。
onStart():
表示Activity正在被启动,这时候的Activity已经被创建好了,完全过了准备阶段,但是没有出现在前台,需要执行onResume()函数才可以进入到前台与用户进行交互。
onResume():
表示Activitiy已经可见了,并且Activity处于运行状态,也就是Activity不止出现在了前台,而且还可以让用户点击,滑动等等操作与它进行交互。
onPause():
表示Activity正在暂停,大多数情况下,Activity执行完onPause()函数后会继续执行onStop()函数,造成这种函数调用的原因是当前的Activity启动了另外一个Activity或者回切到上一个Activity。还有一种情况就是onPause()函数被单独执行了,并没有附带执行onStop()方法,造成这种函数调用的原因很简单,就是当前Activity里启动了类似于对话框的东东。
onStop():
表示Activity即将停止,我们程序员应该在此函数中做一些不那么耗时的轻量级回收操作。
onRestart():
表示Activity正在重新启动。一般情况下,一个存在于后台不可见的Activity变为可见状态,都会去执行onRestart()函数,然后会继续执行onStart()函数,onResume()函数出现在前台并且处于运行状态。
onDestory():
表示Activity要被销毁了。这是Activity生命中的最后一个阶段,我们可以在onDestory()函数中做一些回收工作和资源释放等,比如:广播接收器的注销等。
三、进程的优先级
前台>可见>服务>后台>空
前台:与当前用户正在交互的Activity所在的进程。
可见:Activity可见但是没有在前台所在的进程。
服务:Activity在后台开启了Service服务所在的进程。
后台:Activity完全处于后台所在的进程。
空:没有任何Activity存在的进程,优先级也是最低的。
四、任务栈
任务栈与Activity的启动模式密不可分,它是用来存储Activity实例的一种数据结构,Activity的跳转以及回跳都与这个任务栈有关。详情请看下面的Activity的启动模式。
五、Activity的启动模式
1.Activity为什么需要启动模式?
我们都知道启动一个Activity后,这个Activity实例就会被放入任务栈中,当点击返回键的时候,位于任务栈顶层的Activity就会被清理出去,当任务栈中不存在任何Activity实例后,系统就回去回收这个任务栈,也就是程序退出了。这只是对任务栈的基本认识,深入学习,笔者会在之后文章中提到。那么问题来了,既然每次启动一个Activity就会把对应的要启动的Activity的实例放入任务栈中,假如这个Activity会被频繁启动,那岂不是会生成很多这个Activity的实例吗?对内存而言这可不是什么好事,明明可以一个Activity实例就可以应付所有的启动需求,为什么要频繁生成新的Activity实例呢?杜绝这种内存的浪费行为,所以Activity的启动模式就被创造出来去解决上面所描述的问题。
2.Avtivity的启动模式有哪些?
Activity的启动模式有4种,分别是:standard,singleTop,singleTask和singleInstance。
- 系统默认的启动模式:standard
标准模式,这也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否存在。被创建的实例的生命周期符合典型情况下的Activity的生命周期。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity的任务栈中。比如Activity A启动了Activity B(B是标准模式),那么B就会进入到A所在的任务栈中。有个注意的地方就是当我们用ApplicationContext 去启动standard模式的Activity就会报错,这是因为standard模式的Actiivty默认会进入启动它的Activity所属的任务栈中,但是由于非Activity类型的Context(如ApplicationContext)并没有所谓的任务栈,所以这就会出现错误。解决这个问题的方法就是为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就会为它创建一个新的任务栈,这个时候启动Activity实际上以singleTask模式启动的,读者可以自己仔细体会。 - 栈顶复用模式:singleTop
在这种模式下,如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法被回调,通过此方法的参数我们可以取出当前请求的信息。需要注意的是,这个Activity的onCreate,onStart不会被系统调用,因为它并没有发生改变。如果新的Activity已经存在但不是位于栈顶,那么新的Activity仍然会重新重建。举个例子,假设目前栈内的情况为ABCD,其中ABCD为四个Activity,A位于栈低,D位于栈顶,这个时候假设要再次启动D,如果D的启动模式为singleTop,那么栈内的情况依然为ABCD;如果D的启动模式为standard,那么由于D被重新创建,导致栈内的情况为ABCDD。 - 栈内复用模式:singTask
这是一种单例实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,和singleTop一样,系统也会回调其onNewIntent。具体一点,当一个具有singleTask模式的Activity请求启动后,比如Activity A,系统首先寻找任务栈中是否已存在Activity A的实例,如果已经存在,那么系统就会把A调到栈顶并调用它的onNewIntent方法,如果Activity A实例不存在,就创建A的实例并把A压入栈中。 - 单实例模式:singleInstance
这是一种加强的singleTask模式,它除了具有singleTask模式所有的特性外,还加强了一点,那就是具有此种模式的Activity只能单独位于一个任务栈中,换句话说,比如Activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了。
3.如何为活动设置启动模式?
在AndroidManifest.xml文件当注册活动的代码中去指定
<activity android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
六、scheme跳转协议
Android中的scheme是一种页面内跳转协议,通过自定义scheme协议,可以非常方便的跳转到app中的各个页面,通过scheme协议,服务器可以定制化告诉app跳转到哪个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转到相应页面等等。主要用于以下几种场景:
- 服务器下发跳转路径,客户端根据服务器下发跳转路径跳转相应的页面
- H5页面点击锚点,根据锚点具体跳转路径App端跳转具体的页面
- App端收到服务器端下发的PUSH通知栏消息,根据消息的点击跳转路径跳转相关页面
URL scheme的作用
客户端应用可以向操作系统注册一个 URL scheme,该 scheme 用于从浏览器或其他应用中启动本应用。通过指定的 URL 字段,可以让应用在被调起后直接打开某些特定页面,比如车辆详情页、订单详情页、消息通知页、促销广告页等等。也可以执行某些指定动作,如订单支付等。也可以在应用内通过 html 页来直接调用显示 app 内的某个页面。