2.1 Activity
1.Activity是什么?
Activity是Android的四大组件之一。是用户操作的可视化界面;它为用户提供了一个完成操作指令的窗口。
当我们创建完毕Activity之后,需要调用setContentView()方法来完成界面的显示;以此来为用户提供交互的入口。
2.典型情况下的Activity生命周期?
Activity启动–>onCreate()–>onStart()–>onResume()
点击home键回到桌面–>onPause()–>onStop()
再次回到原Activity时–>onRestart()–>onStart()–>onResume()
退出当前Activity时–>onPause()–>onStop()–>onDestroy()
3.异常情况下的Activity的生命周期 & 数据如何保存和恢复?
在onStop之前调用onSaveInstanceState保存当前Activity状态,当Activity被重新创建后,系统调用
onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象
作为参数传递给onRestoreInstanceState和onCreate方法
onRestoreInstanceState的调用时机发生在onStart之后
4.从Activity A跳转到Activity B之后,然后再点击back键之后,它们的生命周期调用流程是什么?
从Activity A跳转到Activity B
Activity A -> onPause()
Activity B -> onCreate()
Activity B -> onStart()
Activity B -> onResume()
Activity A -> onStop()
点击back键
Activity B -> onPause()
Activity A -> onRestart()
Activity A -> onStart()
Activity A -> onResume()
Activity B -> onStop()
Activity B -> onDestroy()
5.如何统计Activity的工作时间?
Activity开始工作的起点是onResume()而工作的停止点为onPause(),
因此当每次Activity调用onResume()的时候记录一个时间a,每次调用onPause()的时候再记录一个时间b,
那么由b-a可得当次Activity工作的时间。
6.给我说说Activity的启动模式 & 使用场景。
系统默认的启动模式:standard
系统的默认模式,每次启动一个Activity都会重新创建一个新的实例
栈顶复用模式:singleTop
如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),
否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。
使用场景如新闻类或者阅读类App的内容页面。
栈内复用模式:singleTask
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。
重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
使用场景如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,
并且会清空主界面上面的其他页面。
单实例模式:singleInstance
在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。
一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例
( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。
使用场景如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,
比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。
7.如何在任意位置关掉应用所有Activity & 如何在任意位置关掉指定的Activity?
封装一个类,成员变量有一个List集合,当Activity执行onCreate()方法时将当前的Activity实例加入,
遍历这个List且逐一调用finish()即可
给每个启动的Activity一个tag,根据这个tag和集合可达到在任意位置关闭指定Activity的效果。
8.Activity的启动流程(从源码角度解析)?
app启动的过程有两种情况,第一种是从桌面launcher上点击相应的应用图标,
第二种是在activity中通过调用startActivity来启动一个新的activity。
我们创建一个新的项目,默认的根activity都是MainActivity,而所有的activity都是保存在堆栈中的,
我们启动一个新的activity就会放在上一个activity上面,而我们从桌面点击应用图标的时候,由于launcher本身也是一个应用,
当我们点击图标的时候,系统就会调用startActivitySately(),一般情况下,我们所启动的activity的相关信息都会保存在intent中,
比如action,category等等。我们在安装这个应用的时候,系统也会启动一个PackaManagerService的管理服务,
这个管理服务会对AndroidManifest.xml文件进行解析,从而得到应用程序中的相关信息,比如service,activity,Broadcast等等,然后获得相关组件的信息。
当我们点击应用图标的时候,就会调用startActivitySately()方法,而这个方法内部则是调用startActivty(),
而startActivity()方法最终还是会调用startActivityForResult()这个方法。
因为startActivityForResult()方法是有返回结果的,所以系统就直接给一个-1,就表示不需要结果返回了。
而startActivityForResult()这个方法实际是通过Instrumentation类中的execStartActivity()方法来启动activity,
Instrumentation这个类主要作用就是监控程序和系统之间的交互。而在这个execStartActivity()方法中会获取ActivityManagerService的代理对象,
通过这个代理对象进行启动activity。启动会就会调用一个checkStartActivityResult()方法,如果说没有在配置清单中配置有这个组件,就会在这个方法中抛出异常了。
当然最后是调用的是Application.scheduleLaunchActivity()进行启动activity,而这个方法中通过获取得到一个ActivityClientRecord对象,
而这个ActivityClientRecord通过handler来进行消息的发送,系统内部会将每一个activity组件使用ActivityClientRecord对象来进行描述,
而ActivityClientRecord对象中保存有一个LoaderApk对象,通过这个对象调用handleLaunchActivity来启动activity组件,
而页面的生命周期方法也就是在这个方法中进行调用。
9.启动一个其它应用的Activity的生命周期分析。
同4
10.Activity任务栈是什么?在项目中有用到它吗?说给我听听
-android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
-我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
-在我们退出应用程序时,必须把所有的任务栈中所有的activity清除出栈时,任务栈才会被销毁。当然任务栈也可以移动到后台, 并且保留了每一个activity的状态. 可以有序的给用户列出它们的任务, 同时也不会丢失Activity的状态信息。
-需要注意的是,一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈。还有一点就是一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。