Activity组件

 

生命周期

完整生命周期

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接口需要实现createFromParcel();前者从Java对象转化为Parcel对象,后者由Parcel对象转化为Java对象,所以Parcelable序列化和反序列化的能力是依赖于Parcel对象的;

首先调用Parcel.init(),从Native层获取用于保存数据的地址保存在成员变量mNativePtr;

当Parcel对象向Native层写入数据时,按照mNativePtr的地址依次向后写入数据,并且要4字节对齐;当容量不够时,会自动malloc()申请内存;

当Parcel对象从Native层读出数据时,按照mNativePtr的地址依次向后读出数据,并且按照Java对象的成员变量类型对齐、4字节对齐;

所以写入和读出的成员变量的顺序一致,才能保证正确。