-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Activity: Lifecycle and Launch Mode #19
Comments
Viewpager 中两中不同的 Adapter 下,fragment 生命周期的变化:假设有10个Fragment,每个fragment都打印其位置信息,从位置0开始: FragmentStatePagerAdapter但进入页面,停留在 0 位置处,打印日志如下: D/Logger: setUserVisible0, false
D/Logger: setUserVisible1, false
D/Logger: setUserVisible0, true
D/Logger: onAttach0
D/Logger: onCreate0
D/Logger: onAttach1
D/Logger: onCreate1
D/Logger: onCreateView0
D/Logger: onActivityCreated0
D/Logger: onCreateView1
D/Logger: onActivityCreated1 得到的信息如下: setUserVisible 方法在所有方法前调用,之后设置可见的 fragment 为 true。 重要的生命周期为:onAttach -- onCreate -- onCreateView -- onActivityCreated。此时 Fragment 变为活跃状态。 会提前加载下一个Fragment。 此时往后滑动 1 个,打印日志如下: D/Logger: setUserVisible2, false
D/Logger: setUserVisible0, false
D/Logger: setUserVisible1, true
D/Logger: onAttach2
D/Logger: onCreate2
D/Logger: onCreateView2
D/Logger: onActivityCreated2 此时 Fragment 2 创建,共有 3 个framgent实例存在。当前为 Fragment 1, 左右各一个。 继续往后滑动一个: D/Logger: setUserVisible3, false
D/Logger: setUserVisible1, false
D/Logger: setUserVisible2, true
D/Logger: onAttach3
D/Logger: onCreate3
D/Logger: onDestoryView0
D/Logger: onDestroy0
D/Logger: onDetach0
D/Logger: onCreateView3
D/Logger: onActivityCreated3 当前为Fragment 2, 此时 Fragment 0 被销毁,Fragment 3 创建。 滑动tab,直接点击fragment 6, 打印日志如下:
此时变化较大,可见性方面没有变化。 Fragment 5,6,7 被创建。1,2,3被销毁。共计Fragment 实例存在。 viewpager.offscreenPageLimit = 4 可以通过上述方法修改不可见屏幕外的 fragment 的数量。 FragmentPagerAdapter在上述的基础上,此 Adapter 在滑动过程中,其余生命周期方法一致,只是不会调用 D/Logger: onDestroy0
D/Logger: onDetach0 fragment 不会销毁。所以重新创建时: D/Logger: setUserVisible0, false
D/Logger: setUserVisible2, false
D/Logger: setUserVisible1, true
D/Logger: onCreateView0
D/Logger: onActivityCreated0
D/Logger: onDestoryView3 只会重新调用创建view的相关方法,从而保留 fragment 的实例在内存中。 因此可以根据不同的 Fragment 数量来决定使用哪种 adapter。 嵌套 ViewPager在嵌套多个ViewPager的情况下, 从外层开始进行初始化, 其 fragment 实例个数与上述分析保持一致。 D/Logger: onCreateView 0
D/Logger: onCreateView 1
D/Logger: onCreateView 0-0
D/Logger: onCreateView 0-1
D/Logger: onCreateView 1-0
D/Logger: onCreateView 1-1 |
Activity: Lifecycle and Launch Mode
[TOC]
关于 Activty 相关的东西一直以来都是看别人总结的二手资料,从未正真的看过源码,包括官方文档的相关东西都能在源码中找到,所以 多看源码,永远不会错。
继承关系
由于 Activity 的源码太多,一个类就有 8000 行代码,所以找感兴趣,当然,每个类前面的注释特别重要,属于必读内容。
这里先不管接口,继承了 ContextThemeWrapper 类,一直往上走,继承关系如下:
Activity 是什么
英文是这样描述的:
几乎所有的 Activity 都与用户交互,所以几乎都是全屏幕,也有少量的 浮动 window 。
其子类有两个需要实现的方法
##生命周期
当一个新 Activity 启动时,位于当前 Activity Stack 的顶部并且正在运行,之前的 Activity 保存在栈顶下面。
屏幕上可能会有一个或者多个可见的 Activity Stack 。
一个 Activity 只可能会有四种状态:
上面有3个关键流程需要注意以下:
完整的生命周期:start — destroy, 需要在 destory 是释放资源,停止线程的操作等。
可见生命周期:start — stop ,可见但不可交互,此时可以向用户显示 Activity 所需的资源。
比如注册
BroadcastReceiver
来监视界面的改变, stop 是取消注册。随着可见和不可见,会被调用多次。前台周期:resume — pause。
在整个生命周期中,需要实现
onPause()
来提交对数据的更改,并准备暂停与用户的交互;onStop()
来处理屏幕不可见时的问题。两点高版本的改动:
onStop()
方法返回之前,应用程序都不会因为任何情况被杀死。所以在onPause()
之后肯定会安全调用onStop()
, 做数据保存的操作。onSaveInstanceState(android.os.Bundle)
将会在onStop()
之后执行。此外,还有两个生命周期:
onRestart()
:onStop()
之后,但 Activity 重新可见之后调用onNewIntent()
: 当启动模式为SingleTop
, 并且位于栈顶重新启动时,一定在onPause
之后调用。此时getIntent()
为 旧的 intent, 可以使用setIntent()
修改。onSaveInstanceState和onRestoreInstanceState基本作用
Android系统的回收机制会在未经用户主动操作的情况下销毁activity,而为了避免系统回收activity导致数据丢失,Android为我们提供了onSaveInstanceState(Bundle outState)和onRestoreInstanceState(Bundle savedInstanceState)用于保存和恢复数据。
当activity有可能被系统回收的情况下,而且是在onStop()之前。注意是有可能,如果是已经确定会被销毁,比如用户按下了返回键,或者调用了finish()方法销毁activity,则onSaveInstanceState不会被调用。
或者也可以说,此方法只有在activity被异常终止的情况下会被调用。
onSaveInstanceState(Bundle outState)会在以下情况被调用:
onPause -> onSaveInstanceState -> onStop。
onRestoreInstanceState(Bundle savedInstanceState)只有在activity确实是被系统回收,重新创建activity的情况下才会被调用。
第5种情况屏幕方向切换时,activity生命周期如下:
onPause -> onSaveInstanceState -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume
onCreate()里也有Bundle参数,可以用来恢复数据,它和onRestoreInstanceState有什么区别?
因为onSaveInstanceState 不一定会被调用,所以onCreate()里的Bundle参数可能为空,如果使用onCreate()来恢复数据,一定要做非空判断。
而onRestoreInstanceState的Bundle参数一定不会是空值,因为它只有在上次activity被回收了才会调用。
而且onRestoreInstanceState是在onStart()之后被调用的。有时候我们需要onCreate()中做的一些初始化完成之后再恢复数据,用onRestoreInstanceState会比较方便。
启动模式
启动模式允许您定义一个 Activity 的新实例如何与当前任务关联。你可以用两种方式定义不同的启动模式:
Using the manifest file
anduse intent flags
.standord
: 默认模式singleTop
: 栈顶复用模式, 常用于接收通知页面。singleTask
: 新开一个返回栈并创建,或者当返回栈存在时,调用onNewIntent()
。 统一时间只能存在一个该实例。虽然在不同任务栈,但返回时还是会返回之前的 Activity 。, 比如 浏览器, 多次进入走onNewIntent()
, 并且清空上面的页面。singleInstance
, 与“singleTask”相同,只是系统不向包含实例的任务启动任何其他活动。活动总是其任务的唯一成员;由这个启动的任何活动都在一个单独的任务中打开。系统应用, 比如 Launcher, 锁屏应用。The text was updated successfully, but these errors were encountered: