一,Activity面试详解
1,activity的四种状态
- running 活动状态。用户点击屏幕,屏幕做出响应。置于栈顶
- paused 失去焦点状态。用户点击屏幕,无响应。(可能被新的非全屏的activity或一个透明的activity覆盖),成员变量,状态信息存在。内存紧张,activity回收
- stopped 该activity被另一个activity完全覆盖的时候。成员变量,状态信息存在。内存紧张,activity回收
- killed activity被回收
2,activity的生命周期
activity启动->onCreate()->onStart()->onResume()
点击home键回到主界面(activity不可见)->onPause()->onStop()
当我们再次回到原activity时->onRestart()->onStart()->onResume()
退出当前activity时->onPause()->onStop()->onDestroy()
onCreate :Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次该方法。
通常用于初始化设置: 1、为Activity设置所要使用的布局文件。2、为安卓控件绑定监听器等静态的设置操作。onStart(
可见不可交互
):当Activity可见未获得用户焦点不能交互时系统会调用。onResume(
可见可交互
) :当Activity和用户发生交互的时候,触发该方法。onPause (
有一点可见不能交互
):当一个正在前台运行的Activity因为其他的Activity需要前台运行而转入后台运行的时候,触发该方法。onStop(
不可见不能交互
):当Activity被其他的Activity完全覆盖不可见时,触发该方法,如果内存紧张,系统会直接结束这个Activity,而不会触发 onStop 方法。onRestart (
由不可见到可见
):当处于停止状态的Activity需要再次展现给用户的时候,触发该方法。onDestroy :当Activity(用户调用finish()或系统由于内存不足)被系统销毁时调用,(整个生命周期只调用1次)用来释放onCreate ()方法中创建的资源,如结束线程,清空数据,注销广播等。和 onStop 方法一样,如果内存紧张,系统会直接结束这个Activity而不会触发该方法。
具体区别 https://blog.csdn.net/superjunjin/article/details/44674917
3,android进程优先级
参考自:https://blog.csdn.net/qinxiandiqi/article/details/51744782
android对于所有进程的处理态度都是尽可能不杀死
。然而,资源总共就那么多,要是对所有进程都保持宽容的话,资源总会有消耗殆尽的时候。因此,在内存不足的情况,android系统需要根据一定的策略,选择性的杀死部分进程。这个策略就是对所有的进程标记优先级,优先级低的先杀死
。
android将进程的优先级分为5个层次,按照优先级由高到低排列如下:
(1)前台进程(Foreground process)。
它表明用户正在与该进程进行交互操作
,android系统依据下面的条件来将一个进程标记为前台进程:
- 该进程持有一个用户正在与其交互的Activity(也就是这个activity的生命周期方法走到了onResume()方法)。
- 该进程持有一个Service,并且这个Service与一个用户正在交互中的Activity进行绑定。
- 该进程持有一个前台运行模式的Service(也就是这个Service调用了startForegroud()方法)。
- 该进程持有一个正在执行生命周期方法(onCreate()、onStart()、onDestroy()等)的Service。
- 该进程持有一个正在执行onReceive()方法的BroadcastReceiver。
一般情况下,不会有太多的前台进程
。杀死前台进程是操作系统最后无可奈何的做法。当内存严重不足的时候,前台进程一样会被杀死。
(2)可见进程(Visible process)。
它表明虽然该进程没有持有任何前台组件
,但是它还是能够影响到用户看得到的界面。android系统依据下面的条件将一个进程标记为可见进程:
- 该进程持有一个非前台Activity,但这个Activity依然能被用户看到(也就是这个Activity调用了onPause()方法)。例如,当一个activity启动了一个对话框,这个activity就被对话框挡在后面。
- 该进程持有一个与可见(或者前台)Activity绑定的Service。
(3)服务进程(Service process)。
除了符合前台进程和可见进程条件的Service,其它的Service都会被归类为服务进程。
(4)后台进程(Background process)。
持有不可见Activity(调用了onStop()方法)的进程即为后台进程
。通常情况下都会有很多后台进程,当内存不足的时候,在所有的后台进程里面,会按照LRU(最近使用)规则,优先回收最长时间没有使用过的进程
。
(5)空进程(Empty process)。不持有任何活动组件的进程
。保持这种进程只有一个目的,就是为了缓存,以便下一次启动该进程中的组件时能够更快响应
。当资源紧张的时候,系统会平衡进程缓存和底层的内核缓存情况进行回收。
如果一个进程同时满足上述5种优先级中的多个等级条件,android系统会优先选取其中最高的等级作为该进程的优先级
。例如,一个进程持有一个Service(服务进程等级)和一个前台Activity(前台进程等级),那么操作系统会将这个进程标记为前台进程。
另外需要注意的是,如果一个进程为另外一个进程提供服务,那么这个进程的优先级不会低于享受服务的进程
。例如,假设进程A中的content provider为进程B提供服务,或者进程A中有一个Service与进程B中的组件进程绑定,那么进程A的优先级至少要与进程B一致,或者高于进程B。
4,activity启动模式
参考自:
https://blog.csdn.net/mynameishuangshuai/article/details/51491074
实际应用时,取类的TaskId查看所属栈id
,类的hashCode查看类实例id
(1)standard-标准模式
这个模式是默认
的启动模式,即标准模式。每次启动一个Activity都会重写创建一个新的实例
,不管这个实例存不存在,这种模式下,谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈中
。这个Activity它的onCreate(),onStart(),onResume()方法都会被调用。
(2)singleTop-栈顶复用模式
这个模式下,如果新的activity已经位于栈顶,那么这个Activity不会被重写创建,同时它的onNewIntent方法会被调用
(onCreate(),onStart()方法不会被调用),通过此方法的参数我们可以去除当前请求的信息。如果栈顶不存在该Activity的实例,则情况与standard模式相同。
taskAffinity
standard和singleTop启动模式都是在原任务栈中新建Activity实例,不会启动新的Task,即使你指定了taskAffinity属性
。
那么什么是taskAffinity属性呢,可以简单的理解为任务相关性。
- 这个参数标识了一个Activity所需任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名
- 我们可以单独指定每一个Activity的taskAffinity属性覆盖默认值
- 一个任务的affinity决定于这个任务的根activity(root activity)的taskAffinity(
没明白
) - 在概念上,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务
- 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task
(3)singleTask-栈内复用模式
这个模式十分复杂,有各式各样的组合。在这个模式下,如果栈中存在这个Activity的实例就会复用这个Activity
,不管它是否位于栈顶,复用时,会将它上面的Activity全部出栈
,并且会回调该实例的onNewIntent方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过taskAffinity属性指定
。如果这个任务栈不存在,则会创建这个任务栈。
singleTask启动模式启动Activity时,首先会根据taskAffinity去寻找当前是否存在一个对应名字的任务栈
- 如果不存在,则会创建一个新的Task,并创建新的Activity实例入栈到新创建的Task中去
- 如果存在,则得到该任务栈,查找该任务栈中是否存在该Activity实例
- 如果存在实例,则将它上面的Activity实例都出栈,然后回调启动的Activity实例的onNewIntent方法
- 如果不存在该实例,则新建Activity,并入栈
此外,我们可以将两个不同App中的Activity设置为相同的taskAffinity,这样虽然在不同的应用中,但是Activity会被分配到同一个Task中去。
(4)singleInstance-全局唯一模式
该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具有全局唯一性
,即整个系统中就这么一个实例,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。
总结:
standard
,创建一个新的Activity。
singleTop
,栈顶不是该类型的Activity,创建一个新的Activity。否则,onNewIntent。
singleTask
,回退栈中没有该类型的Activity,创建Activity,否则,onNewIntent+ClearTop。
singleInstance
,回退栈中,只有这一个Activity,没有其他Activity。
应用场景:
参考自:https://blog.csdn.net/qq_35114086/article/details/52614714
参考自:https://blog.csdn.net/CodeEmperor/article/details/50481726
singleTop
1,适合接收通知启动的内容显示页面。
比如新闻客户端收到了100个推送,你每次点一下推送他都会走一遍某个activiy(显示新闻只用一个activity,只是内容不同而已)的oncreate,onstart,代价就是创建了那么多的activity(不要以为只有推送,比如qq消息提醒)
a,耗内存
b,走了100次的跳转动画
2,某些业务需求是自己的activity跳转到自己的。
比如 歌曲搜索 你又不会用actionbar,toolbar,那就在activity上面弄个假的呗,搜索完了自己跳转自己现实搜索结果,那就直接用该模式,变化都在onNewIntent()里面对控件进行赋值之类的。而且也没有跳转动画,人们以为这个activity没有动了,多high。
singleTask
适合作为程序入口点。
例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。
singleInstance
适合需要与程序分离开的页面。
例如闹铃提醒,将闹铃提醒与闹铃设置分离。打电话 接通的时候。地图显示的时候。
他们都有一个特点 就是你做完这件事了都会返回到上一界面 而没有下一界面。
singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,再次启动,首先打开的是B。(ac在一个栈,退出c后,退出a,退出ac的栈,再退出b,最后b置于栈顶
)
http://stackoverflow.com/questions/2626218/examples-for-android-launch-modes
5,scheme
参考自:android-Scheme与网页跳转原生的三种方式
(1)什么是 URL Scheme?
android中的scheme是一种页面内跳转协议,是一种非常好的实现机制,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面;通过scheme协议,服务器可以定制化告诉App跳转那个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转页面等
。
(2)URL Scheme应用场景:
客户端应用可以向操作系统注册一个 URL scheme(在activity中添加scheme的信息
),该 scheme 用于从浏览器或其他应用中启动本应用。通过指定的 URL 字段,可以让应用在被调起后直接打开某些特定页面,比如商品详情页、活动详情页等等。也可以执行某些指定动作,如完成支付等。也可以在应用内通过 html 页来直接调用显示 app 内的某个页面。综上URL Scheme使用场景大致分以下几种:
服务器下发跳转路径,客户端根据服务器下发跳转路径跳转相应的页面
H5页面点击锚点,根据锚点具体跳转路径APP端跳转具体的页面
APP端收到服务器端下发的PUSH通知栏消息,根据消息的点击跳转路径跳转相关页面
APP根据URL跳转到另外一个APP指定页面
例:大型公司通过其热门app的一个链接跳转到其公司的其他app(微信-->腾讯新闻)