Android之Fragment
Android 之 Fragment
为什么 Fragment ?
为了让界面在平板上更好地展示;代码复用;Activity 可用来管理 Fragment;可控性更好,可以像普通对象那样自由地创建和控制,传递参数更加容易方便,也不用处理系统相关的事情,显示方式、替换、不管整体还是部分,都可以做到相应的更改;可作为 View Controllers
添加 Fragment
1 | <fragment |
1 | Fragment1 fragment1 = new Fragment1(); |
Fragment 生命周期
几个新方法:
onAttach()
:Fragment 和 Activity 建立关联的时候调用onCreateView()
:为 Fragment 加载布局时调用onActivityCreated()
:当 Activity 中的onCreate()
执行完调用onDestroyView()
:Fragment 中的布局被移除时调用onDetach()
:Fragment 和 Activity 解除关联时调用
注意一点:除了onCreateView()
,其他方法必须调用父类对于该方法的实现。
通信方式:
直接在一个 Fragment 中调用另外一个 Fragment 中的方法。适用于布局文件已定义了的 Fragment。
1
2Fragment1 f1 = (Fragment1) getActivity().getFragmentManager().findFragmentById(R.id.fragment1);
fi.func();使用接口
1
2
3public interface IFunc{
void func();
}
1 | public class Activity1 implements IFunc{ |
1 | public class Fragment1 extends Fragment{ |
- 广播
getActivity()
Fragment 中直接调用 Activity 中的公开方法;onAttach()
之前可以调用fragment.setArguments(bundle)
;Activity 中可有 Fragment 的引用;- Eventbus、数据存储等其他方式;
getActivity()
为 null:异步网络请求的回调中调用此方法会出现空指针的问题。如果 APP 长时间在后台运行,再次进入可能会出现 crash,而且 fragment 会有重叠现象。如果系统内存不足、切换横竖屏、APP 长时间后台运行,Activity 都可能被系统回收然后重建,但 Fragment 并不会随着 Activity 的回收而被回收,创建的所有 Fragment 会被保存到 Bundle 里面,从而导致 Fragment 丢失对应承载它的 Activity。
解决方法:可在onAttach()
获取 Activity 上下文;重叠问题的解决:1.想办法不让 Activity 意外退出重建时保存信息//super.onSaveInstanceState(outState);
(不推荐);2.旋转屏幕时等场景不让 Activity 走生命周期方法android:configChanges="keyboardHidden|orientation|screenSize"
;3.当 Activity 恢复时,取出保存的 Fragment 重新加入即可,即保留了 Activity 的视图状态,也完美地解决了重叠问题。
其他知识点
回退栈管理
1 | Fragment f = new Fragment(); |
Fragment 与 ActionBar 和 MenuItem
a. 在 Fragment 的onCreate()
调用setHasOptionsMenu(true)
b. 然后再 Fragment 类中实现 onCrateOptionsMenu()
c. 如果希望在 Fragment 中处理 MenuItem 的点击,也可以实现onOptionsItemSelected()
,Activity 也可以直接处理该 MenuItem 的点击事件。
没有布局的 Fragment —— 保存大数据
主要用于处理异步请求带来的数据保存问题,尤其是异步请求未完成时屏幕旋转这种现象
- 继承 Fragment,声明引用指向你的有状态的对象
- 当 Fragment 创建时
onCreate()
调用setRetainInstance(boolean)
- 把 Fragment 实例添加到 Activity 中
- 当 Activity 重新启动后,使用 FragmentManager 对 Fragment 进行恢复
DialogFragment 的使用
- 新建对话框布局文件
- 继承 DialogFragment 重写
onCreateDialog()
dialog.show(getFragmentManager(), "testDialog");
Fragment 的startActivityForResult
- 只嵌套了一层 Fragment:Fragment 中使用时,不要使用
getActivity().startActivityForResult()
,而是应该直接使用;如果 Activity 中重写了onActivityResult()
,其中一定要加上super.onActivityResult()
。若违反,则只能传递到 Activity 中而不能到达 Fragment 中的onActivityResult()
。 - 嵌套多层 Fragment:此时是不能传递到第二层的 Fragment 中的。可以通过 FragmentManager 递归调用
fragment.onActivityResult()
。同样需要注意1.中的限制 - 在所有的 Fragment 中若是直接使用
startActivityForResult()
,那么传到 Activity 的onActivityResult()
中的 requestCode 就会不对,resultCode 是对的,当然,传到 Fragment 中也会如此。若是用getActivity().startActivityForResult()
则都会是正确的。当然若是直接返回键返回,那么会自动给一个 resultCode,在重写的时候需要判定 resultCode。
Fragment add
& replace
两种方法不同之处:是否要清空容器再添加 Fragment 的区别,用法上add
配合hide
或者remove
1
2
3
4
5FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, fragment1).hide(fragment2).commit();
ft.replace(R.id.fragment_container, fragment1).commit();
参考引用
对于Fragment的一些理解
Android Fragment完全解析,关于碎片你所需知道的一切
Android Fragment学习与使用—高级篇
对于Fragment的一些理解
关于Fragment与Fragment、Activity通信的四种方式
Fragment中调用getActivity为null的问题
fragment重叠的完美解决方案
谈谈Fragment中的onActivityResult
Fragment add replace 区别