参考:java
Fragment 就是一个 Activity 布局的一部分,能够把 Activity 的一部分布局抽离出来到 Fragment 中,而且 Fragment 也能够执行逻辑。就是把 Activity 复杂的内容抽离成几个碎片,而后拼凑起来,在 Activity 布局中,只须要引入各个不一样的 Fragment 就能够 了。android
好比咱们常见的布局,底部导航,而后每一个模块对应不一样的 Fragment。其实也是彻底能够不使用 Fragment 的,一个页面中包含各个模块的布局,而后经过点击导航来决定隐藏哪些模块。这样写的话一个 Activity 中的代码逻辑会很是多,全部模块都融合到一个 Activity 中了,至关冗余,耦合。若是用 Fragment 就灵活多了,Activity 只须要根据导航显示对应的 Fragment 就能够了。markdown
若是别的地方须要某一个模块,直接拿出对应的 Fragment 就能够了。若是都写在 Activity 中那抽离出来就费劲了,也增长了不肯定性。ide
再好比一个例子:网易新闻 手机端 和平板端。oop
平板端是新闻的标题和详情都在一个页面中。手机是详情在单独的一个页面。这样咱们就能够将 标题 和 详情写成两个 Fragment。充分利用了。布局
Fragment
spa
具体的 Fragment.net
FragmentManager
code
是管理 Fragment 的orm
FragmentTransaction
经过事务来进行添加 Fragment、隐藏、移除 等操做 Fragment 动做,事务保证了原子性
transaction.add()
向 Activity 中添加 Fragment,只是添加 Fragment,不影响以前 Fragment 的声明周期,这一点和 Activity 不同,Activity 会由于新 Activity 而走生命周期。而 .add
不会。假如 FragmentA 已经在 Activity 中了,这个时候启动了 FragmentB,A 的生命周期是不会有任何变化的,仍是处于 onResume
,并不会由于 B
处于 onResume
而有影响。
transaction.remove()
从 Activity 中移除一个 Fragment
。若是这个 Fragment 没有被添加到回退栈中,则实例被销毁。若是添加到回退栈了,会执行 onDestroyView
实例并不会被销毁。
transaction.replace()
使用 Fragment 替换当前,至关于先移除以前的 Fragment(remove()) 而后再 add()
transaction.hide()
隐藏当前 Fragment。仅仅是设为不可见。不会销毁
transaction.show()
显示以前隐藏的 Fragment
detach()
会将 view 从 UI 中移除。和 remove 不一样的是,此时 Fragment的状态依然由 FragmentManager 维护
attach()
重建 view 视图,附加到UI上显示
.addToBackStack()
是将事务放入回退栈,能够认为一个事务中能够有多个 Fragment .addToBackStack()
作的是将这个事务放入回退栈。
相似于咱们每添加一个 Activity 都会默认放入回退栈中,若是想要 Fragment 放入回退栈中,那么就须要借助启动 Fragment 的事务了,调用事务的 .addToBackStack()
方法。
默认状况下,按下返回键的时候的操做是从回退栈中弹出一个事务。
按下返回键的时候,是从返回栈中弹出一个事务(Fragment)。显示栈顶的事务(对应的 Fragment)
若是当前栈顶的Fragment 已经执行过 destroyView
了,则会从新执行生命周期(从 createView
开始)
若是任务栈中只有一个Fragment,则此时按下返回键,进行的操做是把这个 Fragment 销毁。
在 Fragment A 中启动另外一个 Fragment B 这个时候 .addToBackStack()
是将 A 加入栈中。
// 直接在 xml 中添加
<fragment android:id="@+id/fragment" android:layout_width="match_parent" android:layout_height="200dp" android:name="com.syd.good.feature.fragment.fragment.FragmentMy" />
复制代码
在代码中获取的这个 Fragment
经过
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment);
复制代码
注意静态添加 Fragment
的生命周期
E/FragmentMy: onAttach
E/FragmentMy: onCreate
E/FragmentMy: onCreateView
E/FragmentMy: onViewCreated
E/FragmentStaticActivity: onCreate()
E/FragmentMy: onActivityCreated
E/FragmentMy: onStart
E/FragmentStaticActivity: onStart()
E/FragmentStaticActivity: onResume()
E/FragmentMy: onResume
// 中止
E/FragmentMy: onPause
E/FragmentStaticActivity: onPause()
E/FragmentMy: onStop
E/FragmentStaticActivity: onStop()
E/FragmentMy: onDestroyView
E/FragmentMy: onDestroy
E/FragmentMy: onDetach()
E/FragmentStaticActivity: onDestroy()
复制代码
动态添加,通常都会选择加载到 FrameLayout
布局上,是由于 FrameLayout
布局足够简单,能够减小没必要要的布局加载。
Fragment 的布局只是附着在 FrameLayout
上,做为 FrameLayout
的 子 View ,并无取代 FrameLayout
<FrameLayout android:id="@+id/fl" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" />
复制代码
getSupportFragmentManager().beginTransaction()
.add(R.id.fl, new FragmentOne())
.add(R.id.fl, new FragmentTwo())
.commit();
复制代码
Fragment 不管是不是全屏仍是一半的,执行生命周期都同样
执行结果:
E/FragmentOne: onAttach
E/FragmentOne: onCreate
E/FragmentTwo: onAttach()
E/FragmentTwo: onCreate()
E/FragmentOne: onCreateView
E/FragmentOne: onViewCreated
E/FragmentOne: onActivityCreated
E/FragmentOne: onStart
E/FragmentOne: onResume
E/FragmentTwo: onCreateView
E/FragmentTwo: onActivityCreated
E/FragmentTwo: onStart
E/FragmentTwo: onResume
复制代码
返回
E/FragmentOne: onPause
E/FragmentTwo: onPause
E/FragmentOne: onStop
E/FragmentTwo: onStop
E/FragmentOne: onDestroyView
E/FragmentOne: onDestroy
E/FragmentOne: onDetach()
E/FragmentTwo: onDestroyView
E/FragmentTwo: onDestroy
E/FragmentTwo: onDetach()
复制代码
onHiddenChanged()
和普通的生命周期没有关系,只是调用 hidden
的时候会调用而已。
经过上面 .add
的方式添加 Fragment
只是将 Fragment 添加到指定的布局中,以后再添加 Fragment 是互相不影响的,在布局上看 FrameLayout
有两个子View(FragmentOne、FragmentTwo) 相互重叠。
主 Activity 中一次启动两个 Fragment ,并将这个事务加入到回退栈中。
getSupportFragmentManager().beginTransaction()
.add(R.id.fl, new FragmentOne())
.add(R.id.fl, new FragmentTwo())
.addToBackStack(null)
.commit();
复制代码
这个时候按下返回键的结果是,从回退栈中弹出这个事务,意味这销毁这两个 Fragment
执行结果
Fragment 从 Activity 中脱离,留下 Activity
E/FragmentOne: onAttach
E/FragmentOne: onCreate
E/FragmentTwo: onAttach()
E/FragmentTwo: onCreate()
E/FragmentOne: onCreateView
E/FragmentOne: onViewCreated
E/FragmentOne: onActivityCreated
E/FragmentOne: onStart
E/FragmentOne: onResume
E/FragmentTwo: onCreateView
E/FragmentTwo: onActivityCreated
E/FragmentTwo: onStart
E/FragmentTwo: onResume
// 按下返回键
E/FragmentTwo: onPause
E/FragmentTwo: onStop
E/FragmentTwo: onDestroyView
E/FragmentTwo: onDestroy
E/FragmentTwo: onDetach()
E/FragmentOne: onPause
E/FragmentOne: onStop
E/FragmentOne: onDestroyView
E/FragmentOne: onDestroy
E/FragmentOne: onDetach()
复制代码
假如没有 addToBackStack()
的时候,按下返回键,则直接退出 Activity 了。
在上面的基础上,在启动的 FragmentTwo 中添加方法
tvAdd.setOnClickListener((view1) -> {
Log.e("add", "add");
getFragmentManager().beginTransaction()
.add(R.id.fl, new FragmentThree())
.commit();
});
复制代码
这个时候只是在 fl
中又添加了一个 FragmentThree
,而且这个事务没有加入到回退栈中,这个时候按下返回键,结果是:
页面没有发生任何改变,可是上一次保存在回退栈的事务被弹出了
E/FragmentTwo: onPause
E/FragmentTwo: onStop
E/FragmentTwo: onDestroyView
E/FragmentTwo: onDestroy
E/FragmentTwo: onDetach()
E/FragmentOne: onPause
E/FragmentOne: onStop
E/FragmentOne: onDestroyView
E/FragmentOne: onDestroy
E/FragmentOne: onDetach()
复制代码
这个时候再按下返回键
Activity 就会被销毁。
在例子1的基础上,在添加 FragmentTwo 中添加方法
tvAdd.setOnClickListener((view1) -> {
Log.e("add", "add");
getFragmentManager().beginTransaction()
.add(R.id.fl, new FragmentThree())
// 添加了将此事务入栈
.addToBackStack(null)
.commit();
});
复制代码
这个时候再按下返回键,是将这个栈顶的事务退出,这个时候例子1 中的事务就处于栈顶了。页面显示的就是例子1中的页面了。
再次按下返回键,是把例子1中的事务弹出,这个时候留下的就只有 Activity 了,再次按下返回键,弹出 Activity。
getFragmentManager.findFragmentByTag() 或者 findFragmentById()
获取getActivity
获取当前绑定的 Activity 实例Fragment 不该该直接操做其余的 Fragment。应该由管理者 Activity 来进行。
采用接口回调的形式
凡是加入了回退栈 .addToBackStack(null)
以前加入的 Fragment 都不会被销毁。
好比:
Activity A 中
getSupportFragmentManager().beginTransaction()
.add(R.id.fl, new FragmentOne())
.add(R.id.fl, new FragmentTwo())
.commit();
复制代码
FragmentTwo 中
getSupportFragmentManager().beginTransaction()
.replace(R.id.fl, new FragmentThree())
.addToBackStack(null)
.commit();
复制代码
请注意 Activity A 中是没有 addToBackStack 的 ,即便这样在 FragmentTweo
中 replace
后 FragmentOne
和 FragmentTwo
也不会被销毁,而是走 onDestroyView()
方法。按下返回键后,恢复 FragmentOne
和 FragmentTwo
从 onCreateView
开始
若是没有 .addToBackStack(null)
的话,那么 FragmentOne
和 FragmentTwo
就会被销毁了。而且按下返回键的时候,就销毁掉 Activity 了。
页面1 addTo
页面2 没有
E/FragmentThree: onAttach() E/FragmentThree: onCreate() E/FragmentTwo: onPause E/FragmentTwo: onStop E/FragmentTwo: onDestroyView E/FragmentOne: onPause E/FragmentOne: onStop E/FragmentOne: onDestroyView E/FragmentThree: onCreateView E/FragmentThree: onActivityCreated E/FragmentThree: onStart E/FragmentThree: onResume E/FragmentTwo: onDestroy E/FragmentTwo: onDetach() E/FragmentOne: onDestroy E/FragmentOne: onDetach()