生命周期
完整生命周期
onCreate()/onRestart() -> onStart() -> onRestoreInstanceState() -> onPostCreate() -> onNewIntents() -> onActvityResults() -> onResume() -> onPause() -> onSaveInstanceState() -> onStop() -> onDestroy()
这是最全的生命周期回调,但不是每次都会全部调用。
旋转屏幕时生命周期
约定onPause() -> onSaveInstanceState() -> onStop() -> onDestroy()为“销毁”;
onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()为“重建”。
清单文件中Activity标签有android:configChanges属性。这个属性的意思是,当满足某种条件时,就会认为是Activity的配置改变了,从而调用Activity生命周期及onConfigChanged()回调。
android:configChanges属性的可选值有:orientation(当屏幕方向发生变化)及其它。于是有三种情况:不设置、满足、不满足。
- 不设置切到横屏:销毁 -> 重建
- 不设置切到竖屏:销毁 -> 重建 -> 销毁 -> 重建
- 满足切到横屏:销毁 -> 重建
- 满足切到竖屏:销毁 -> 重建 -> onConfigChanged()
- 不满足切到横屏:onConfigChanged()
- 不满足切到竖屏:onConfigChanged() -> onConfigChanged()
按下Home键时生命周期
- 按下:onPause() -> onSaveInstanceState() -> onStop()
- 恢复:onRestart() -> onStart() -> onRestoreInstanceState() -> onResume()
两个Activity跳转时生命周期
- 当两个都是全屏,前跳到后时:前.onPause() -> 后.onCreate() -> 后.onStart() -> 后.onResume() -> 前.onStop()
- 当两个都是全屏,后回到前时:后.onPause() -> 前.onRestart() -> 前.onStart() -> 前.onResume() -> 后.onStop() -> 后.onDestroy()
- 当后不是全屏,前跳到后时:前.onPause() -> 后.onCreate() -> 后.onStart() -> 后.onResume()
- 当后不是全屏,后回到前时:后.onPause() -> 前.onResume() -> 后.onStop() -> 后.onDestroy()
弹出/隐藏Dialog时生命周期
没有发生生命周期回调。只有TaskRecord中ActivityRecord状态变化才会引起Activity生命周期变化。
下拉/收起通知栏时生命周期
没有发生生命周期回调。这也说明“系统窗口”遮挡(比如Toast)不会引起Activity生命周期变化。如果要监听下拉/收起通知栏,可以重写onWindowFocusChanged()。
onSaveInstanceState()/onRestoreInstanceState()什么时候会调用?
- 旋转屏幕时且android:configChanges属性没设置或满足时;
- 按下Home键时;
- 由于内存不足回收Activity时。
Activity生命周期与Fragment生命周期的关系
- 创建:Activity.onCreate() -> Fragment.onAttach() -> Fragment.onCreate() -> Fragment.onCreateView() -> Fragment.onActivityCreated() -> Activity.onStart() -> Fragment.onStart() -> Activity.onResume() -> Fragment.onResume();
- 销毁:Fragment.onPause() -> Activity.onPause() -> Fragment.onStop() -> Activity.onStop() -> Fragment.onDestroyView() -> Fragment.onDestroy() -> Fragment.onDetach() -> Activity.onDestroy()。
特殊启动
一次启动多个Activity
Context.startActivities(Intent[] intents);排在最后的最先Rusume;其余都不创建Activity,但创建ActivityRecord并插入TaskRecord;每后退一次,当某个Activity将要显示出来时才会创建。
重启应用
- 当应用死亡时,可以使用Intent.makeRestartActivityTask()构造Intent;
- 当应用存活时,可以构造Intent(xxx, rootActivity.class)并添加FLAG_CLEAR_TOP(rootActivity无法重建)。
数据交换
Activity向Activity
- 利用Intent传递数据,包括启动Activity和广播;
- 利用Application,要注意考虑Application被回收可能造成空指针;
- 利用单例模式;
- 利用文件或数据库;
Activity向Service
- 如果Activity与Service在同一进程中,可以继承自Binder类,实现getService(),返回Service对象;然后在onBinder()中返回Binder对象;在Activty中创建实现了ServiceConnection接口的对象,作为bindService()的参数;其中onServiceConnected()将返回Binder对象,通过它就可以获得Service对象,即可向Service传递信息;
- 如果Activity与Service在同一进程中,还可以用本地广播;
- 如果Activity与Service在不同一进程中,且不要求Service具备多线程处理能力,可以继承自Handler类,实现handleMessage()处理事件,并用Handler构建一个Messenger,在onBinder()中返回Messenger.getBinder();在Activity中创建实现了ServiceConnection接口的对象,作为bindService()的参数;其中onServiceConnected()将返回Binder对象,通过它就可以获得Handler对象,即可向Service传递信息;
- 如果Activity与Service在不同一进程中,且要求Service具备多线程处理能力,用AIDL。
- 如果Activity与Service在不同一进程中,还可以用全局广播。
Service向Activity
只能用广播。
Serializable和Pacelable接口的区别
- Serializable使用IO读写存储在硬盘上,而Parcelable是直接在内存中读写;
- Serializalbe会使用反射,序列化和反序列化过程需要大量I/O操作,Parcelable自已实现序列化和反序列化,不需要用反射;
- Pacelable 和 Serializable 序列化的作用是不同的,Pacelable 是为了“传递”,而 Serializable 是为了“储存”。
Serializable的原理
Serializable接口本身是一个标记接口,没有任何方法。它的序列化/反序列化实现是依赖ObjetcOutputStream/ObjectInputStream。
Pacelable的原理
Parcelable接口需要实现writeToParcel(),Creator
首先调用Parcel.init(),从Native层获取用于保存数据的地址保存在成员变量mNativePtr;
当Parcel对象向Native层写入数据时,按照mNativePtr的地址依次向后写入数据,并且要4字节对齐;当容量不够时,会自动malloc()申请内存;
当Parcel对象从Native层读出数据时,按照mNativePtr的地址依次向后读出数据,并且按照Java对象的成员变量类型对齐、4字节对齐;
所以写入和读出的成员变量的顺序一致,才能保证正确。