原文:The Liskov Substitution Principle (LSP, lsp) is a concept in Object Oriented Programming that states: Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it 中文:** 如果对每一个类型为 S 的对象 o1,都有类型为 T 的对象 o2,使得以 T 定义的所有程序 P 在所有的对象 o1 代换 o2 时,程序 P 的行为没有变化,那么类型 S 是类型 T 的子类型。** 通俗版中文:所有引用基类(父类)的地方必须能透明地使用其子类的对象。
多数原因:你在调用了getActivity()时,当前的 Fragment 已经onDetach()了宿主 Activity.比如:你在 pop 了 Fragment 之后,该 Fragment 的异步任务仍然在执行,并且在执行完成后调用了getActivity()方法,这样就会报 NULLPOINTEXCEPTION; 解决方法:(对于 Fragment 已经onDetach()这种情况,我们应该避免在这之后再去调用宿主 Activity 对象,比如取消这些异步任务,当我们的团队可能会有粗心大意的时候,所以下面给出的方法会保证安全)
在 Fragment 基类里设置一个 Activity mActivity 的全局变量,在onAttach(Activity act)里赋值,使用 mActivity 代替getActivity(),保证 Fragment 即使在 onDetach 后,仍持有 Activity 的引用(有 MermoryLeak 风险。)
如果你add()了几个 Fragment,使用show()/hide()等方法控制显示,比如微信、QQ 的底部 tab 等情景,如果你什么都不做的话,在“内存重启”后回到前台,app 的这几个 Fragment 界面会重叠。
原因
FragmentManager 帮我们管理 Fragment,当发生“内存重启”,他会从栈底向栈顶的顺序一次性恢复 Fragment;但是因为没有保存 Fragment 的 mHidden 属性,默认为 false,即 show 状态,所以所有的 Fragment 都是以 show 的形式恢复,即发生了界面重叠现象。(如果是replace(),恢复形式和 Activity 一致,只有当你的 pop 之后上一个 Fragment 才开始重新恢复,所以使用replace()不会造成重叠现象。)
发生 Fragment 重叠的根本原因在于FragmentState没有保存 Fragment 的显示状态,即mHidden,导致页面重启后,该值为默认的 false,即 show 状态,所以导致了 Fragment 的重叠。因此自己去维护一个mSupportHidden值即可解决问题: Fragment 基类代码: