Fragment笔记

Posted 「已注销」

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Fragment笔记相关的知识,希望对你有一定的参考价值。

Fragment笔记

Fragment的产生与介绍

android运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视。针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后拷贝一份,修改布局以适应平板等超级大屏的。难道无法做到一个App可以同时适应手机和平板么,当然了,必须有啊。Fragment的出现就是为了解决这样的问题。你可以把Fragment当成Activity的一个界面的一个组成部分,甚至 Activity的界面可以完全有不同的Fragment组成,更帅气的是Fragment拥有自己的生命周期和接收、处理用户的事件,这样就不必在Activity写一堆控件的事件处理的代码了。更为重要的是,你可以动态的添加、替换和移除某个Fragment。

为什么要使用fragment

  1. 单Activity+多Fragment:

一个app仅有一个Activity,界面皆是Frament,Activity作为app容器使用。优点:性能高,速度最快。参考:新版知乎 、google系app

  1. 多模块Activity+多Fragment

优点:速度快,相比较单Activity+多Fragment,更易维护

  1. 无视图的fragment 保存数据用
  • activity的onSaveInstanceState(Bundle outState)能保存的数据量有限,当有大量数据要保存的时候用无视图的fragment
  • Activity异常销毁时,onSaveInstanceState能保存的数据有限,数据过大容易oom。所以我们可以在onSaveInstanceState时attach一个Fragment,并将要存储的大数据保存到这个Fragment。当Activity重建时找到这个Fragment,再从中取出那些数据

FragmentPagerAdapter与FragmentStatePagerAdapter

Fragment的生命周期


  • Fragment 主要用于定义Fragment
  • FragmentManager 主要用于在Activity中操作Fragment
  • FragmentTransaction 保证一些列Fragment操作的原子性,熟悉事务这个词,一定能明白
  • 获取FragmentManager的方式
  1. getFragmentManager()

  2. v4中,getSupportFragmentManager

  • 主要的操作都是FragmentTransaction的方法
  1. FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

  2. transaction.add() 往Activity中添加一个Fragment

  3. transaction.remove() 从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。

  4. transaction.replace()使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体

  5. transaction.hide() 隐藏当前的Fragment,仅仅是设为不可见,并不会销毁

  6. transaction.show() 显示之前隐藏的Fragment

  7. detach() 会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。

  8. attach() 重建view视图,附加到UI上并显示。

  9. transatcion.commit()//提交一个事务

  • Fragment Arguments
    setArguments方法必须在fragment创建以后,添加给Activity前完成
  • Fragment与Activity通信
  • Fragment与ActioBar和MenuItem集成
  1. 静态使用fragment

    注意点:

    1. 嵌套了fragment 能
      //作业: 尝试下 fragment嵌套 静态使用fragment
    2. 静态加载一旦添加就不能在运行时删除
    3. 静态fragment 在哪儿初始化的?
    4. fragment一定要有一个没有参数的构造函数

    fragment 为什么需要一个空构造? 看源码

  2. 动态使用fragment 90%

获得FragmentManager对象,通过getSupportFragmentManager()
获得FragmentTransaction对象,通过fm.beginTransaction()
调用add()方法或者repalce()方法加载Fragment;
最后调用commit()方法提交事务

androidx jetpack下面的fragment

v4包下的fragment 有bug
< 24: fragment 重叠问题 onActivityResult分发结果(fragment嵌套) 出栈(popstack(tag,id) popstackimmdate )
转场动画

= 28

注意点:

  1. getActivity == null 请求网络接口

解决方案: 不建议fragment要使用宿主activity getActivity
//TODO: [解决方案]在onAttach(Activity activity)里赋值,使用mActivity代替getActivity(),
// 保证Fragment即使在onDetach后,仍持有Activity的引用(
// 有引起内存泄露的风险,但是异步任务没停止的情况下,本身就可能已内存泄漏,相比Crash,这种做法“安全”些)
@Override
public void onAttach(Context context)
super.onAttach(context);
Log.i(“Zero”, "onAttach : " + getActivity());

bugly

  1. Can not perform this action after onSaveInstanceState
    解决方案:
    不能在onSaveInstanceState之后的生命周期里面commit fragment
    不要在子线程commit fragment 已经走完onSaveInstanceState

  2. fragment 重叠

  3. 屏幕旋转 activity 生命周期
    竖屏 -》 横屏 1
    横屏 -》 竖屏 2
    android:configChanges=“orientation” sdk > 23 sdk < 23
    走 onConfigurationChanged

    原因:
    onCreate add fragment
    onDestroy
    屏幕旋转 onCreate 又会执行 又会重新add一次 fragment (系统自动恢复了一个 )
    why?
    fragment 自动有一个恢复机制

    解决方案:

    1. onSaveInstanceState activity失去自动存储的功能 super
    2. if(savedInstanceState == null)add fragment

    内存重启: fragment 重叠 ( 接了个电话,系统内存不足,杀掉了你的activity )
    打开手机上的“开发者选项”中的“不保留活动”选项,模拟内存重启

fragment 常见操作
add(@NonNull Fragment fragment, @Nullable String tag)

tag : findFragmentByTag
add(@IdRes int containerViewId, @NonNull Fragment fragment,
@Nullable String tag)

containerViewId: 指定fragment添加到那个viewgroup findFragmentById

fragment 传参问题:不要写有参数的构造函数,这是错误的写法
内存重启 自动恢复:只会调用无参的构造函数 fragment 成员变量没有保存
public void setArguments(@Nullable Bundle args)
Bundle getArguments()

添加到回退栈
addToBackStack(@Nullable String name)
popBackStack()
name:
popBackStack(@Nullable final String name, final int flags)

fragment嵌套 回退栈问题 (单activity + fragment )

解决方案:

  1. 自定义
    open class LifeCycleFragment : Fragment(), OnBackPressed
    interface OnBackPressed
    fun onBackPressed()

    在activity
    override fun onBackPressed()
    super.onBackPressed()
    //自己管理回退

  2. 使用navigation

多次add fragment 到同一个位置
重叠问题
fragment 根布局 设置背景
调用hide隐藏上一个添加的

add 与 replace的区别
add 往containerViewId的容器里面添加fragment view
replace将containerViewId的容器里面之前添加的view全部清空
add replace 千万不要混合使用 要么全部用add 要么全部用replace

remove 操作
if (fragment != null && fragment.isAdded)

fragment a

add … remove +1 + -1 = 0 show hide show

popBackStack() 按照栈 弹出的顺序回退 abcd d c b a
popBackStack(@Nullable final String name, final int flags)

abcd popBackStack(b,0) ab
popBackStack(b,0) a

保存数据

setRetainInstance(true)

add replace hide show -> commit
简单API 背后隐藏了什么操作

FragmentActivity: AMS控制Activity的生命周期,FragmentActivity在一系列的dispatchXXX
调用FragmentController来控制Fragment的生命周期

FragmentController:是一个代理

FragmentHostCallback: 被FragmentController持有,有一个FragmentManagerImpl,真正的进行fragment操作

FragmentContainer: :view容器

FragmentTransaction:
Fragment操作的事务,每个FragmentTransaction对象,代表着系列Fragment操作的事务。

  • 操作Fragment的添加,删除,隐藏,显示时,都要使用FragmentTransaction。
  • FragmentTransaction其实是个抽象类,真正的实现类为BackStackRecord

BackStackRecord: BackStackRecord实现了FragmentTransaction,每一个BackStackRecord对象,都代表了一次Fragment操作事务。

Op: Op对象,主要保存了FragmentTransaction操作事务中的单次操作,是相对于Fragment而言的。每个Op对象,保存了操作的Fragment对象,切换动画等对象
add -> new Op
把fragment 和操作的命令 OP_ADD 映射

vip handler源码分析 post (runnable,msg)

commitNow 为什么不运行添加到回退栈
commit
1237456 -> 654321

开启一个事务

。。。。。 N 个 Op

commit

事务操作
操作 command 意义
add OP_ADD 添加fragment
remove OP_REMOVE 删除fragment
replace OP_REPLACE 替换fragment
show OP_SHOW 显示fragment
hide OP_HIDE 隐藏fragment
attach OP_ATTACH 依附activity
detach OP_DETACH 从activity分离

cmd firstOutFragments lastInFragements
OP_ADD - 被添加的fragment
OP_REPLACE 被替换的fragment 新的fragment
OP_REMOVE 被删除的fragment -
OP_HIDE 被隐藏的fragment -
OP_SHOW - 被显示的fragment
OP_DETACH 被detach的fragment -
OP_ATTACH - 被attach的fragment

executeOps
cmd 调用FragmentManager方法
OP_ADD addFragment
OP_REPLACE removeFragment->addFragment
OP_REMOVE removeFragment
OP_HIDE hideFragment
OP_SHOW showFragment
OP_DETACH detachFragment
OP_ATTACH attachFragment

moveToState
状态表格
值 状态 意义 入口方法
0 INITIALIZING Fragment尚未初始化或者已经被销毁 dispatchDestroy
1 CREATED Fragment已被创建 dispatchDestoryView
2 ACTIVITY_CREATED Fragemtn所在Activity已经创建成功 dispatchActivityCreated
3 STARTED Fragment已经可见,但是还不可以接收点击事件 dispatchPause
4 RESUMED Fragment已经可见并且可以接收点击事件 dispatchResume
已经废弃
3 STOPPED Fragment已经被创建,但是尚未不可见 dispatchStop

fragment的state 与Activity 的生命周期不是等同

可见 与可交互

moveToState() Activity的生命周期

oncreate调用的时候,不管fragments 之前的状态 xxx -> CREATED Index

以上是关于Fragment笔记的主要内容,如果未能解决你的问题,请参考以下文章

Android Fragment生命周期及静态加载

Android中Fragment与Activity之间的交互(两种实现方式)

Fragment总结

Docker学习笔记走进docker的世界

Fragment 使用详解

Android:Fragment