探究Fragment生命周期
一个Activity可以同时组合多个Fragment,一个Fragment也可被多个Activity 复用。Fragment可以响应自己的输入事件,并拥有自己的生命周期,但它们的生命周期直接被其所属的Activity的生命周期控制。
一、Fragment状态
与Activity类似的是,Fragment也存在如下4种状态:
- 运行状态:当前Fmgment位于前台,用户可见,可以获得焦点。
- 暂停状态:其他Activity位于前台,该Fragment依然可见,只是不能获得焦点。
- 停止状态:该Fragment不可见,失去焦点。
- 销毁状态:该Fragment被完全删除,或该Fragment所在的Activity被结束。
结合之前学习Activity的状态,理解Fragment的状态非常简单。
很多地方都在说明 Fragment有三个状态,包括官方文档没有提到Fragment的 销毁状态。这也是合理的,因为处于销毁状态的Fragment基本不可用了,只能等着被回收。
二、Fragment生命周期
Fragment的生命周期与Activity的生命周期十分相似,如下图所示:
从上图可以看出,Activity中的生命周期方法,Fragment中基本都有,但是Fragment比Activity多几个方法。各生命周期方法的含义如下:
- onAttach():当该Fragment被添加到Activity时被回调。该方法只会被调用一次。
- onCreate(Bundle savedStatus):创建Fragment时被回调。该方法只会被调用一次。
- onCreateView():每次创建、绘制该Fragment的View组件时回调该方法,Fragment将会显示该方法返回的View 组件。
- onActivityCreated():当 Fragment 所在的Activity被启动完成后回调该方法。
- onStart():启动 Fragment 时被回调。
- onResume():恢复 Fragment 时被回调,在onStart()方法后一定会回调 onResume()方法。
- onPause():暂停 Fragment 时被回调。
- onStop():停止 Fragment 时被回调。
- onDestroyView():销毁该 Fragment 所包含的View组件时调用。
- onDestroy():销毁 Fragment 时被回调。 该方法只会被调用一次。
- onDetach():将该 Fragment 从Activity中删除、替换完成时回调该方法,在onDestroy()方法后一定会回调 onDetach()方法。该方法只会被调用一次。
正如开发Activity时可以根据需要有选择性地覆盖指定方法一样,开发Fragment时也可根据需要有选择性地覆盖指定方法。其中最常见的就是覆盖onCreateView()方法——该方法返回的View将由Fragment显示出来。
三、示例验证
为了掌握Fragment生命周期,接下来通过案例 “Fragment生命周期”来学习。本案例实现了一个Activity加载了一个Fragment,具体步骤如下:
首先创建一个布局文件fragment_lifecycle.xml,在其中简单添加一个文本框,代码如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Fragment生命周期" android:textColor="#1418e6" android:textSize="18sp"/></LinearLayout>
新建一个LifeCycleFragment类,继承Fragment基类,并重写其全部生命周期方法,并在每一个生命周期方法里面将对应的方法名输出到Logcat,代码如下:
package com.jinyu.cqkxzsxy.android.fragmentlifecycle;import android.app.Fragment;import android.content.Context;import android.os.Bundle;import android.support.annotation.Nullable;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;public class LifeCycleFragment extends Fragment { private static final String TAG = "LifeCycleFragment"; @Override public void onAttach(Context context) { super.onAttach(context); Log.d(TAG, "onAttach"); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate"); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "onCreateView"); View view = inflater.inflate(R.layout.fragment_lifecycle, container, false); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.d(TAG, "onActivityCreated"); } @Override public void onStart() { super.onStart(); Log.d(TAG, "onStart"); } @Override public void onResume() { super.onResume(); Log.d(TAG, "onResume"); } @Override public void onPause() { super.onPause(); Log.d(TAG, "onPause"); } @Override public void onStop() { super.onStop(); Log.d(TAG, "onStop"); } @Override public void onDestroyView() { super.onDestroyView(); Log.d(TAG, "onDestroyView"); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); } @Override public void onDetach() { super.onDetach(); Log.d(TAG, "onDetach"); }}
修改Activity的布局文件activity_main.xml,这里简单使用静态加载的方式,代码如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:id="@+id/fragment_one" android:name="com.jinyu.cqkxzsxy.android.fragmentlifecycle.LifeCycleFragment" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout>
修改MainActivity文件,同样也重写其全部生命周期方法,并在每一个生命周期方法里面将对应的方法名输出到Logcat,代码如下:
package com.jinyu.cqkxzsxy.android.fragmentlifecycle;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate"); setContentView(R.layout.activity_main); } @Override public void onStart() { super.onStart(); Log.d(TAG, "onStart"); } @Override protected void onRestart() { super.onRestart(); Log.d(TAG, "onRestart"); } @Override public void onResume() { super.onResume(); Log.d(TAG, "onResume"); } @Override public void onPause() { super.onPause(); Log.d(TAG, "onPause"); } @Override public void onStop() { super.onStop(); Log.d(TAG, "onStop"); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); }}
运行程序,可以看到下图所示界面:
这时候打开Logcat观察其中打印的信息,可以看到下图所示日志信息:
可以看到,Activity第一次加载Fragment并显示出来获得焦点时,会依次执行onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart ->onResume。
此时按下设备的Home键,观察Logcat中打印的日志信息,如下图所示:
可以看到,当按下Home键后,会依次执行onPause -> onStop。
这个时候再恢复打开示例程序,界面会再次显示出来,观察Logcat中打印的日志信息,如下图所示:
可以看到,当回到程序界面恢复时,会依次执行onStart -> onResume。
继续按下设备的Back键,观察Logcat中打印的日志信息,如下图所示:
可以看到,当按下Back键,退出程序会依次执行onPause -> onStop -> onDestoryView -> onDestory -> onDetach。
通过上述操作,可以看到Fragment的生命周期方法执行顺序和前面的生命周期图完全吻合。
同时可以看到,当显示Fragment的时候都先执行Activity方法,当销毁的时候都是先执行 Fragment的方法,这样更好理解Fragment是嵌套在Activity中 。
至此,Fragment的生命周期体验结束,当和Activity对比起来会发现非常简单,仅仅只是多个几个方法而已。
目前设计到的Fragment都是单一的,下一期来学习如何同时加载和操作多个Fragment,敬请期待。
写在最后
今天就先到这里,如果有问题欢迎留言一起探讨,也欢迎加入Android零基础入门技术讨论微信群,共同成长!
如果该系列分享对你有帮助,就动动手指关注、点赞、留言吧,你的互动就是对我最大的鼓励!
此文章版权为微信公众号分享达人秀(ShareExpert)——鑫鱻所有,若需转载请联系作者授权,特此声明!
- 分布式唯一ID生成器Twitter 的 Snowflake idworker java版本
- 使用 Phoenix-4.11.0连接 Hbase 集群 ,并使用 JDBC 查询测试
- 高并发分布式系统中生成全局唯一Id汇总
- ZooKeeper 可视化监控 zkui
- 关于RBAC(Role-Base Access Control)的理解
- Spring Boot 中使用 Kafka
- 如何评价一段代码
- java系统高并发的解决方案
- Spring Boot 中使用 Redis
- 使用 Jedis 连接操作 Redis
- 浅析ReDoS的原理与实践
- 使用 Executors,ThreadPoolExecutor,创建线程池,源码分析理解
- CentOS+Nginx+Tomcat搭建高性能负载均衡集群
- Java 四种线程池的使用
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【colab pytorch】指定使用的显卡
- Python自学成才之路 迭代器的使用
- 回溯法--全排列
- 【colab pytorch】张量操作
- 『开发技巧』python :与-> 操作来给函数参数增加元信息
- 【python-leetcode78-子集】子集
- 【colab pytorch】模型定义
- 初级爬虫--爬取拉勾网职位信息
- requests库
- hadoop之完全分布式集群配置(centos7)
- XPath
- 62. Vue 饿了么Mint UI组件的基本使用
- 【colab pytorch】数据处理
- requests+lxml+xpath爬取豆瓣电影
- python之子类继承父类时进行初始化的一些问题