Andorid Fragment 使用
Fragment 概要
Fragment表示 Activity 中的行为或用户界面部分。您可以将多个片段(片段就是指 Fragment )组合在一个 Activity 中来构建多窗格 UI,以及在多个 Activity 中重复使用某个片段。您可以将片段视为 Activity 的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件,并且您可以在 Activity 运行时添加或移除片段(有点像您可以在不同 Activity 中重复使用的“子 Activity”)。
片段必须始终嵌入在 Activity 中,其生命周期直接受宿主 Activity 生命周期的影响。 例如,当 Activity 暂停时,其中的所有片段也会暂停;当 Activity 被销毁时,所有片段也会被销毁。
当您将片段作为 Activity 布局的一部分添加时,它存在于 Activity 视图层次结构的某个 ViewGroup 内部,并且片段会定义其自己的视图布局。您可以通过在 Activity 的布局文件中声明片段,将其作为 `` 元素插入您的 Activity 布局中,即静态添加。或者通过将其添加到某个现有 ViewGroup,利用应用代码进行动态插入。不过,片段并非必须成为 Activity 布局的一部分;您还可以将没有自己 UI 的片段用作 Activity 的不可见工作线程。
生命周期
Fragment的生命周期是托管给Activity 而不是系统调用
onAttach():Fragment和Activity相关联时调用。可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。
onCreate():Fragment被创建时调用。
onCreateView():创建Fragment的布局。
onActivityCreated():当Activity完成onCreate()时调用。
onStart():当Fragment可见时调用。
onResume():当Fragment可见且可交互时调用。
onPause():当Fragment不可交互但可见时调用。
onStop():当Fragment不可见时调用。
onDestroyView():当Fragment的UI从视图结构中移除时调用。
onDestroy():销毁Fragment时调用。
onDetach():当Fragment和Activity解除关联时调用
参考一张图:
可以看到除重新打开页面都是Fragment 生命周期方法先执行,很好理解,因为要先用fragment 绘制ui
Fragment的使用
静态加载
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"
android:layout_height="match_parent">
<fragmentclass="com.chavez.dev.fragment.ListFragment"
android:id="@+id/titles"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent"/>
</LinearLayout>
现在layout 文件声明一个<fragment>标签,其中class 为你要实现的fragment
实现fragment 的类必须是Fragment的子类或者是Fragment子类的子类
然后可以去覆写相应的生命周期方法
publicclassListFragmentextendsandroidx.fragment.app.ListFragment{
@Override
publicvoidonActivityCreated(@NullableBundlesavedInstanceState) {
//fragment重叠问题,加if 判断fragment 有没被系统杀掉并且重新初始化
if(savedInstanceState==null){
/**
code
**/
}
}
}
补充:每当用户旋转屏幕时,activity会破坏,并重新创建(layout-land layout-port) onSaveInstanceState()和onRestoreInstanceState() 方法就会执行。
动态加载
通过代码的形式,动态的在某个viewGroup(<LinearLayout> 或者<FragmentLayout>)中添加fragement
通过Fragment 事务的形式添加
getSupportFragmentManager().beginTransaction().add(R.id.My_VIEW_GROUP,newMyFragment).commit();
注意:getSupportFragmentManager() 方法替换的是已经被官方弃用的getFragmentManager()
也可以替换原来的fragment
// 替换原来显示的内容
FragmentTransactionft=getFragmentManager().beginTransaction();
// 设置转换效果
ft.replace(R.id.oidFragment,newFragment);
// 将事务添加到返回栈, 这样即使fragment 被移除了也不会被销毁,系统只是停止该fragment,并且用户按返回键时将其恢复(直观效果,按返回键会回到上一个fragment 而不是直接退出)
ft.addToBackStack(null);
// 提交 fragment 事务
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);ft.commit();
也可在xml 声明一个viewGroup(一般动态添加都声明,作为fragmeng容器)
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/index"android:layout_width="match_parent"android:layout_height="match_parent">
<FrameLayout
android:id="@+id/detail"
android:layout_weight="2"
android:layout_width="0px"
android:layout_height="match_parent"/>
</LinearLayout>
然后通过FragmentManager 去获取这个Fragmentlayout
DetailFragmentdetail=(DetailFragment)getFragmentManager().findFragmentById(R.id.detail);
如果detail为空时,生成实例
if(detail==null){
// 创建一个DetailFragment 实例 用于显示当前选中内容的详情
detail=DetailFragment.newInstance();
/**
code
**/
}
也可以创建一个纯Fragment的layout
<?xmlversion="1.0" encoding="utf-8"?>
<FrameLayoutandroid:id="@+id/item_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"xmlns:android="http://schemas.android.com/apk/res/android"/>
然后创建对应Activity 并且继承FragmentActivity 类
提交fragment 事务
getSupportFragmentManager().beginTransaction().add(R.id.item_detail,detailFragment).commit();
补充:commit()是异步的,commitNow()是同步的,为了不阻塞主线程,一般建议使用commit()
在Activity中获取Fragment
Fragmentfragment=getFragmentManager.findFragmentById(R.id.fragment_container);
在Fragment 获取其寄宿的Activity
在 fragment 中可以调用 getActivity() 获取 activity 的实例并调用 activity 里的方法和布局