我要做 Android 之Fragment

Q:谈一谈Fragment的生命周期?

一:首先说说时间节点:Fragment 是在 Android3.0+ 以后,Android 新增了 Fragments,在没有 Fragment 之前。一个屏幕只能放一个 Activity。这是一个起源时间大家什么时候引入。(ps:为了屏幕适配的原因翻译为碎片)

Fragment 概要

学习 Fragment 的时候可以联系之前学习过的 Activity ,因为它们有很多相似点:都可包含布局,有自己的生命周期,Fragment 可看似迷你活动。正如 Fragment 的名字--碎片,它的出现是为了解决 Android 碎片化 ,它可作为Activity 界面的组成部分,可在 Activity 运行中实现动态地加入、移除和交换。一个 Activity 中可同时出现多个Fragment,一个 Fragment 也可在多个 Activity 中使用。

Activity 代表了一个屏幕的主体,而 Fragment 可以作为 Activity 的一个组成元素。
一个 Activity 可以有若干个(0或n)Fragment 构成。你可以把 Fragment 想象成 Activity 中的一个控件,只不过相对于一般控件,Fragment 与 Activity 联系更为紧密,随着 Activity 的生命周期变化,Fragment 也随之相应不同的生命周期函数。
Fragment 从功能上讲相当于一个子活动(Activity),它可以让多个活动放到同一个屏幕上,也就是对用户界面和功能的重用,因为对于大屏设备来说,纯粹的 Activity 有些力不从心。


fr01.png

2.Fragment生命周期

先来看官方文档提供的有关Fragment生命周期的图片。


fr02.png

由上图可以发现 Fragment 和 Activity 的生命周期很相似,可以说大致周期的情况是基本相同的。现在只需要在介绍几个 Activity 中没有讲过的新方法。

onAttach(): 当 Fragment 和 Activity 建立关联的时候调用

onCreateView() : 当 Fragment 创建视图的时候调用

onActivityCreated(): 当与 Fragment 相关联的 Activity 完成 onCreate() 之后调用

onDestoryView(): 当 Fragment 中的布局被移除的时候调用

onDetach(): 当 Fragment 和 Activity 解除关联的时候调用

所以根据 Activity 的周期方法我们可以大致判断周期画面

(1)打开页面的时候

onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume 

(2)按下主屏幕键

onPause -> onStop

(3)重新打开界面

onStart -> onResume

(4)按后退键

onPause -> onStop -> onDestroyView -> onDestroy -> onDetach

加载到 Activity 中的 Fragment 在各种变化下方法的调用顺序更值得注意。需要提一句的是,Activity 的 FragmentManager 负责调用队列中 Fragment 的生命周期方法,只要 Fragment 的状态与 Activity 的状态保持了同步,托管 Activity 的 FragmentManager 便会继续调用其他生命周期方法以继续保持 Fragment 与 Activity 的状态一致。

注意注意注意

当 Activity 加入 Fragment

(1)打开界面

Fragment onCreate() -> Fragment onCreateView() -> Activity onCreate() -> Fragment onActivityCreated() -> Activity onStart() -> Fragment onStart() -> Activity onResume() -> Fragment onResume()

(2)按下主屏幕键

Fragment onPause() -> Activity onPause() -> Fragment onStop() -> Activity onStop()

(3)重新打开界面

Activity onRestart() -> onActivity start() -> Fragment onStart() -> Activity onResume() -> Fragment onResume()

(4)按后退键退出

Fragment onPause() -> Activity onPause() -> Fragment onStop() -> Activity onStop() -> Fragment onDestroyView() -> Fragment onDestroy() -> Fragment onDetach() -> Activity onDestroy()

Fragment 生命周期与 Activity 生命周期的一个关键区别在于,Fragment 的生命周期方法是由托管 Activity 而不是操作系统调用的。 Activity 中生命周期方法都是 protected,而 Fragment 都是 public,也能印证了这一点,因为 Activity 需要调用 Fragment 那些方法并管理它。

三:加载 Fragment 方法

现在就来学习如何在 Activity 中加载 Fragment

(1)静态加载:在托管 Activity 的 layout 文件中声明 Fragment

静态加载 Fragment 大致过程分为四步:

fr03.png

我会在下方给出一个 demo 让大家感受以下 (ps:一定要自己动手写一遍,感受和看的真的不一样,会给你带来肌肉记忆。)

第一:新建一个 frag_layout.xml 布局,这是 Fragment 的布局,这里就只有一个显示 TextView 和 Button。

fr04.png

第二:新建一个 MyFragment 类并继承 Fragment,这里引用 v4 下的包,具有兼容性。顺便提一下,正常我们引入包的时候都用 v4 或者 v7 下的包,这里的包都是向下兼容,否则可能会出现意想不到的问题。我们在这里重写 onCreateView()方法,这个方法里通过 LayoutInflate 的 inflate() 方法将刚定义的 frag_layout 布局加载进来并得到一个 View,在 return 这个 view 就 OK。


fr07.png

第三:在 main_xml 布局中修改,使用 < fragment > 标签来添加碎片,并且切记切记要加上 android:name 属性。之后会有自动提示,加载的完整形式是 包名.类名


fr08.png

第四步:在 MainActivity 中加载main布局。现在MyFragment就完成了静态加载到 MainActivity 中,这时碎片里的控件自然也是活动的一个部分,可直接在活动中获取到 Button 的实例,来注册点击事件了。

fr09.png

看下运行结果:

fr06.png

second:动态加载:在托管 Activity 通过代码动态添加

动态加载的代码也非常简单,直接看例子。修改main.xml,将整个< fragment >删掉。但还保留一个LinerLayout的空间并且还给了 Id,为何这样做?马上揭秘。


fr11.png

接下来在MainActivity中添加几行代码:


fr10.png

可将整个过程大致分为三个步骤:

第一步,先用 getFragmentManager() 方法获取一个FragmentManager对象,再通过它的 beginTransaction() 获取一个FragmentTransaction的实例。

第二步,用beginTransaction. add() 方法将MyFragemnt实例添加到main布局里LinearLayout里,终于知道之前铺垫的Id是怎么回事了。一定要注意,add()方法里的第一个参数是容器视图资源Id,而不是layout。容器视图资源Id有两个作用:告知FragmentManager,碎片视图应该出现在活动视图的什么地方;它也是FragmentManager队列中碎片的唯一标识符。而静态加载时碎片的唯一标识符正是在活动布局里< fragment>下的id。

第三步:调用beginTransaction. commit() 提交。另外,如果允许用户通过按下返回按键返回到前一个Fragment状态,在调用commit()之前先调用 addToBackStack(true) 方法。

这里注意到动态加载进来的Fragment里的控件并不能直接在活动中findViewById得到,那么如何实现点击效果呢,学完下一个知识点就有办法了。

Fragment 与 Activity 之间的通信

在活动中可以通过调用 FragmentManager 的 findFragmentById() 方法来得到相应碎片的实例,继而可以调用碎片里的方法。以上面demo举例,如果想得到静态加载碎片的实例,可在MainActivity添加代码如下:

MyFragment myFragment = (MyFragment) getFragmentManager(). findFragmentById(R.id.fragment);

如果想得到动态加载碎片的实例,代码如下:

MyFragment myFragment = (MyFragment)fragmentManager(). findFragmentById(R.id.layout);

在碎片中也可以通过调用getActivity()方法来得到和当前碎片相关联的活动实例,这样调用活动里的方法就变得轻而易举了。比如想在MyFragment得到MainActivity的实例:

MainActivity activity = (MainActivity)getActivity();

于是碎片和活动可以很方便地进行通信了。再想一想碎片和碎片之间如何进行通信?先在一个碎片中可以得到与它相关联的活动,然后再通过这个活动去获取另外一个碎片的实例,这样实现了不同碎片之间的通信了。


fr12.png

只要这样我们就有能够正常的使用了。

就我个人而言,正常 APP 中都是一个 Activity 带几个 Fragment,所以这时候我们需要通过适配器来实现。实现之后每一个 Fragment 对应的操作依然在各自的 Fragment 中来实现。而不是在 Activity 中。

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

推荐阅读更多精彩内容