Android基础-Activity
Google Doc: https://developer.android.google.cn/guide/components/activities/
一、Activity生命周期
Activity生命周期.jpg- 当Activity启动时,依次会调用onCreate、onStart、onResume。
- 当Activity退居后台时(不可见,点击Home或者被新的Activity完全覆盖),onPause、onStop会依次被调用。
- 当Activity重新回到前台(从桌面回到原Activity或者被覆盖后又回到原Activity)时,onRestart、onStart、onResume会依次被调用。
- 当Activity退出销毁时(点击back键),onPause、onStop、onDestroy会依次被调用。
- 退出当前Activity时–>onPause()–>onStop()–>onDestroy()依次被调用。
当一个 Activity 启动另一个 Activity 时,第一个 Activity 暂停并停止(但如果它在后台仍然可见,则不会停止)时,同时系统会创建另一个 Activity,在创建第二个 Activity 前,第一个 Activity 不会完全停止。更确切地说,启动第二个 Activity 的过程与停止第一个 Activity 的过程存在重叠。
当 Activity A 启动 Activity B 时:
- Activity A 的
onPause()
方法执行。 - Activity B 的
onCreate()
、onStart()
、onResume()
方法依次执行。(Activity B 现在具有用户焦点。) - 然后,如果 Activity A 在屏幕上不再可见,则其
onStop()
方法执行。
此时在Activity B中按下Back键,则:
- B.onPause()->A.onRestart->A.onStart->A.onResume-> B.onStop->B.onDestroy。
二、Activity异常生命周期
1 相关系统配置改变导致Activity被杀死并重新创建(一般指横竖屏切换)
- 竖屏调整为横屏,则onPause,onSaveInstanceState,onStop,onDestroy,onCreate,onStart,onRestoreInstanceState,onResume依次被调用;
- onSaveInstanceState和onRestoreInstanceState只有在Activity异常终止时才会被调用的,正常情况是不会调用这两个方法的;
- 在onSaveInstanceState方法和onRestoreInstanceState方法中,系统会自动帮我们恢复一定的数据,如当前Activity的视图结构、文本框的数据、ListView的滚动位置等,这些View相关的状态系统都会帮我们恢复,因为每个View也有onSaveInstanceState方法和onRestoreInstanceState方法
2 内存不足导致低优先级的Activity被杀死
当系统内存不足的时候,系统就会按照一定的优先级去杀死目标Acitivity的进程来回收内存,并且此时Activity的onSaveInstanceState方法会被调用来存储数据,并在后续Activity恢复时调用onRestoreInstanceState方法来恢复数据
三、Activity销毁重建
当系统配置发生变化后,Activity会被重建。
如果不想Activity在屏幕旋转后导致销毁重建时,可以设置configChange=“orientation”;当SDK版本大于13时,还需额外添加一个“screenSize”的值。
设置了这两个参数后,当横竖屏切换时,Activity不会再重建并且也不会调用onSaveInstanceState方法和onRestoreInstanceState方法,而是会回调onConfigurationChanged方法。
四、Activity通信
-
通过将数据封装在Bundle对象中 ,然后在Intent跳转的时候携带Bundle对象
该方法可以传递基本数据类型和String类型的数据,如果传递的是对象就需要进行序列化。 -
类静态变量
通过public static定义Activity的静态变量然后在其他Activity使用类名.变量名传递。 -
Application
通过在Application 中的全局静态变量来实现。 -
EventBus
当传输的数据量较大的时候Parcelable虽然很便捷,但是会出现异常TransactionTooLargeException。此时可以用插件EventBus。
EventBus 使用的是发布-订阅者模型,发布者通过EventBus发布事件,订阅者通过EventBus订阅事件。当发布者发布事件时,订阅该事件的订阅者的事件处理方法将被调用。
五、Activity启动模式
Activity启动模式分四种:Standard 标准模式,SingleTop 栈顶复用模式、SingleTask 栈内复用模式、SingleInstance 单实例模式。
1 Standard 标准模式
每次启动一个Activity,都会又一次创建一个新的实例入栈,无论这个实例是否存在。
生命周期:
每次被创建的实例Activity的生命周期符合典型情况,它的onCreate、onStart、onResume都会被调用。
举例:
Activity栈中已有A、B、C三个Activity,C处于栈顶。若从C Acticity跳转到另一个C Activity,结果是新建一个C Activity入栈,成为栈顶。
Activity启动模式-Standard.png2 SingleTop 栈顶复用模式
- 情况1:若需要创建的Activity已处于栈顶,此时会直接复用栈顶的Activity,不会再创建新的Activity;
- 情况2:若需要创建的Activity不处于栈顶,此时会又一次新建一个新Activity入栈,同Standard模式。
生命周期:
情况1下,栈顶Activity直接被复用,它的onCreate、onStart不会被调用,因为它并没有发生改变,但onNewIntent会被调用(Activity被正常创建时不会回调此方法)。
举例:
Activity栈中已有A、B、C三个Activity,C处于栈顶。情况一:从C跳转到另一个C,结果是直接复用栈顶的C,不再新建;情况二:从C跳转到A,结果是新建一个A入栈,成为栈顶。
Activity启动模式-SingleTop.png使用场景:
假设在当前的Activity中要启动同类型的Activity,此时建议将该Activity指定为SingleTop模式,能够降低Activity的创建,节省内存。
3 SingleTask 栈内复用模式
若需要创建的Activity已处于栈中,不会再新建Activity,而是将存在栈中的Activity上面的其他所有Activity销毁,使它成为栈顶。
生命周期:
同SingleTop情况一同样,仅会回调Activity的onNewIntent方法。
举例:
Activity栈中已有A、B、C三个Activity,C处于栈顶。情况一:从C跳转到C,则直接复用栈顶的C;情况二:从C跳转到A,则将A上面的B、C销毁,使A成为栈顶。
Activity启动模式-SingleTask.png使用场景:
最常见的应用场景就是保持应用开启后仅仅有一个Activity的实例。
比如:应用中展示的主页,假设用户在主页跳转到其他页面,多次操作后想返回到主页,假设不使用SingleTask模式,在点击返回的过程中会多次看到主页,不合理。
4 SingleInstance 单实例模式
全局单例模式,加强的SingleTask。具有此模式的Activity仅仅能单独位于一个任务栈中。经常适用于系统中的应用,比如Launch、锁屏键的应用等,整个系统中仅有一个。
举例:
A Activity是该模式,启动A后,系统会为它创建一个单独的任务栈,由于栈内复用的特性,新的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁。
六、使用方式
使用方法有两种:
- AndroidManifest.xml中为Activity指定launchMode。
- 动态指定,通过Intent的addFlags方法动态指定启动模式。
优先级:
第2种比第1种优先级高,若两者同时存在,以2为准
限定范围:
第1种无法为Activity直接指定FLAG_ACTIVITY_CLEAR_TOP标识;
第2种无法为Activity指定SingleInstance模式。
注意:须考虑Activity跳转时携带页面参数的问题
当一个Activity设置了SingleTop或者SingleTask模式后,跳转此Activity出现复用原有Activity的情况时,此Activity的onCreate方法将不会再调用。onCreate方法仅会在第一次创建Activity时被调用。
而一般onCreate方法中会进行该页面的数据初始化、UI初始化,假设页面的展示数据无关页面跳转传递的參数,则不必操心此问题;若页面展示的数据就是通过getIntent() 方法来获取,那么问题就会出现:getIntent()获取的一直都是老数据,根本无法接收跳转时传送的新数据!
这时我们需要另外一个回调 onNewIntent(Intent intent)方法。此方法会传入最新的intent,这样我们就能够解决上述问题。这里建议的方法是再次调用setIntent。然后重新初始化数据和UI。
七、相关Flags
1 FLAG_ACTIVITY_NEW_TASK
为Activity指定SingleTask启动模式,与AndroidManifest.xml指定效果相同。
2 FLAG_ACTIVITY_SINGLE_TOP
为Activity指定SingleTop启动模式,与AndroidManifest.xml指定效果相同。
3 FLAG_ACTIVITY_CLEAN_TOP
具有此标记的Activity,启动时会将与其同栈的其他Activity出栈。一般与SingleTask启动模式一起出现。它会完毕SingleTask的作用,但事实上SingleTask启动模式默认具有此标记的作用。
4 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此标记的Activity不会出现在Activity列表中。
使用场景:某些情况下不希望用户通过历史列表回到某个Activity时,此标记便可以实现该效果。
等同于AndroidManifest.xml中指定Activity属性:android:excludeFromRecents="true"
八、监听Activity生命周期
在Application中调用 registerActivityLifecycleCallbacks(),通过 ActivityLifecycleCallbacks 接口的实现,完成对Activity各个生命周期信息的采集。
比如哪个Activity在什么时间处于onCreate、onStop等等,进而统计出Activity的使用时间和使用次数。