Android学习笔记之Fragment

1.Fragment 是什么?

Fragment 是 Android 自 3.0 版本开始引入的一种可以嵌入在 Activity 当中的UI片段,主要是为了能在不同分辩率屏幕上进行更为动态和灵活的UI设计,让程序更加合理和充分利用大屏幕空间。

2.Fragment 为什么被称为第五大组件

  1. 使用频率高;
  2. 有自己的生命周期;
  3. 可以灵活加载到Activity中;
  4. 虽然有自己的生命周期,并不像 Activity 那样独立的,需要依附 Activity。

3.Fragment 加载到 Activity 的两种方式

  • 静态加载:作为XML标签添加到 Activity 的布局文件当中。

步骤1:新建fragment.xml文件
步骤2:在Fragment中,重写onCreateView方法,为Fragment设置xml布局文件,转换成view对象返回。

//传递三个参数:
//LayoutInflater inflater表示布局填充器或者加载器,将xml文件转换成view对象。
//ViewGroup container表示fragment插入activity的布局视图对象。
//Bundle saveInstanceState表示存储上一个fragment的信息。
View view = inflater.inflate(R.layout.fragment,container,false);
return view;

步骤3:在activity布局中,通过fragment标签引入fragment,记住是name属性

<fragment
    android:name="com.songsong.FragmentTest.fragment"
    ...
/>
  • 动态加载:动态在 Activity 中添加 Fragment 。 (常用)
//前提1:先创建 Fragment类并继承 Fragment,在onCreateview设置XML布局文件。
//前提2:在Activity的XML布局文件中准备好布局容器R.id.lin_id

//步骤1:创建Fragment的管理器对象FragmentManager 
FragmentManager manager = getFragmentManager();
//步骤2:获取Fragment的事务对象并且开启事务
FragmentTransaction transaction = manager.beginTransaction();
//步骤3:调用事务中相应的动态操作Fragment的方法执行,add、remove和replace
transaction.add(R.id.lin_id, new Fragment1());
//模拟返回栈
transaction.addToBackStack(null);
//步骤4:提交事务
transaction.commit();

4.Fragment 和 Activity 之间的通信

通常,Fragment 与 Activity 通信存在三种情形:

  • Activity 操作内嵌的 Fragment,
  • Fragment 操作宿主 Activity,
  • Fragment 操作同属 Activity中的其他 Fragment。
  • 在 Activity 中调用 Fragment 中的 findFragmentById 方法;
//通过FragmentManage的findFragmentById得到实例,然后就可以调用fragment里的方法
RightFragment rf = getFragmentManager().findFragmentById(R.id.right_fragment);
  • 在 Fragment 中调用 Activity 中的 getActivity 方法;
//fragment中调用Activity的方法,getActivity本身就是一个Context对象。
MainActivity act = getActivity();
  • Fragment 与 Fragment 之间的通信:
    先在一个碎片中可以得到与它相关联的活动,然后再通过这个活动去获取另外一个碎片的实例,这样实现了不同碎片之间的通信了 。

5.Fragment 的生命周期

Fragment生命周期

简单的Fragment流程图—— onAttach->onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume ->创建成功-> onPause->onStop->onDestroyView -> onDestroy->onDetach。其中和Activity有不少名称相同作用相似的方法,而不同的方法有:

  • onAttach():当Fragment和Activity建立关联时调用
  • onCreateView():当Fragment创建视图时调用
  • onActivityCreated():当与Fragment相关联的Activity完成onCreate()之后调用
  • onDestroyView():在Fragment中的布局被移除时调用
  • onDetach():当Fragment和Activity解除关联时调用

Fragment操作生命流程图:

  • 打开 Fragment:onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume
  • 替换 Fragment:onPause->onStop->onDestroyView
  • 返回旧 Fragment:onCreateView->onActivityCreated->onStart->onResume
  • 退出 Fragment:onPause->onStop->onDestroyView->onDestroy->onDetach

6.FragmentPagerAdapter 与 FragmentStatePagerAdaper 区别:

  • FragmentPagerAdapter :FragmentPagerAdapter 在切换 ViewPager 的时候,只是把 Fragment的UI 与 Activity的UI 脱离开来,并不回收内存。所以它适用页面较少的情况。(在其源码 DestroyItem 方法中的最后一行,mCurTransaction.detach 可知)

  • FragmentStatePagerAdaper :由于 FragmentStatePagerAdaper 在每次切换 ViewPager 的时候,它是回收内存的。又因为在页面较多的情况下会更耗内存,所以它适合页面较多的情况。(在源码 DestroyItem 方法中的最后一行,mCurTransaction.remove 可知 )

7.Fragment 的 replace、add、remove 方法

  • replace 是 FragmentManager 的方法,是将 Activity 最上层的 Fragment 替换掉。
  • add 将 Fragment 的实例添加到 Activity 的最上层
  • remove 将 Fragment 的实例从 Activity 的队列中删除

8.Fragment 特点

  • Fragment 可以作为 Activity 界面的一部分组成出现;
  • 可以在一个 Activity 中同时出现多个 Fragment,并且一个 Fragment 也可以在多个 Activity 中使用;
  • 在 Activity 运行过程中,可以添加、移除或者替换 Fragment;
  • Fragment 可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主 Activity 的生命周期影响。
  • Fragment 可以轻松得创建动态灵活的 UI 设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。
  • Fragment 解决 Activity 间的切换不流畅,轻量切换。
  • Fragment 替代 TabActivity 做导航,性能更好。
  • Fragment 做局部内容更新更方便,原来为了达到这一点要把多个布局放到一个 activity 里面,现在可以用多 Fragment 来代替,只有在需要的时候才加载 Fragment,提高性能。

9.Activity和Fragment的异同?

  • Activity和Fragment的相似点在于,它们都可包含布局、可有自己的生命周期,Fragment可看似迷你活动。
  • 不同点是,由于Fragment是依附在Activity上的,多了些和宿主Activity相关的生命周期方法:如onAttach()、onActivityCreated()、onDetach();另外,Fragment的生命周期方法是由宿主Activity而不是操作系统调用的,Activity中生命周期方法都是protected,而Fragment都是public,也能印证了这一点,因为Activity需要调用Fragment那些方法并管理它。

10.怎么理解Activity和Fragment的关系?

  • 正如Fragment的名字“碎片”,它的出现是为了解决Android碎片化 ,它可作为Activity界面的组成部分,可在Activity运行中实现动态地加入、移除和交换。
  • 一个Activity中可同时出现多个Fragment,一个Fragment也可在多个Activity中使用。
  • 另外,Activity的FragmentManager负责调用队列中Fragment的生命周期方法,只要Fragment的状态与Activity的状态保持了同步,宿主Activity的FragmentManager便会继续调用其他生命周期方法以继续保持Fragment与Activity的状态一致。

11.何时会考虑使用Fragment?

  • 用两个Fragment封装两个界面模块,这样只使一套代码就能适配两种设备,达到两种界面效果;(新闻列表、新闻内容)
  • 单一场景切换时使用Fragment更轻量化,如ViewPager和Fragment搭配使用。

12.Activity向引入的Fragment传值

  • 步骤1:Activity中创建Fragment对象,调用setArguments(Bundle)方法存储值。
  • 步骤2:Fragment中调用getArguments()获取传递Bundle对象解析获取具体值。
存储值
获取值

13.Fragment向Activity传值

步骤1:Fragment 中定义传值的回调接口,在生命周期 onAttach() 方法中获取接口的实现。

private MyListener listener;
@Override
public void onAttach(...){
   ...
   listener = (MyListener)getActivity();
}
public interface MyListener{
   public abstract void sendMessage(String str);
}

步骤2:Fragment 需要传值的位置调用接口回调方法传值。

listener.sendMessage(info);

步骤3:Activity 实现回调接口重写回调方法获取传递的值。

@Override
public void sendMessage(String str){
  if(null !=str && !"".equals(str)){
    //显示处理
    }
}

14.Fragment与Fragment之间的传值

fragment.jpg

13.遇到过哪些关于Fragment的问题,如何处理的?

  • getActivity()空指针:这种情况一般发生在在异步任务里调用getActivity(),而Fragment已经onDetach(),此时就会有空指针,解决方案是在Fragment里使用 一个全局变量mActivity,在onAttach()方法里赋值,这样可能会引起内存泄漏,但是异步任务没有停止的情况下本身就已经可能内存泄漏,相比直接crash,这种方式显得更妥当一些。

  • Fragment视图重叠:在类onCreate()的方法加载Fragment,并且没有判断saveInstanceState==null或if(findFragmentByTag(mFragmentTag) == null),导致重复加载了同一个Fragment导致重叠。(PS:replace情况下,如果没有加入回退栈,则不判断也不会造成重叠,但建议还是统一判断下)

@Override 
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 在页面重启时,Fragment会被保存恢复,而此时再加载Fragment会重复加载,导致重叠 ;
    if(saveInstanceState == null){
    // 或者 if(findFragmentByTag(mFragmentTag) == null)
       // 正常情况下去 加载根Fragment 
    } 
}

Fragment状态保存 startActivityForResult 是哪个类的方法,在什么情况下使用?

本文参考资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容