关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android Fragment生命周期深入探究

    Android Fragment生命周期深入探究

    2015-01-19 00:00:00 出处:AigeStudio
    分享

    Fragment是Android中的重要组件,在Android 3.0的时候添加进来。

    关于Fragment的生命周期,我相信了解过的开发人员都应该把以下方法脱口而出:onAttach, onCreate, onCreateview, onViewCreated, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.

    当Fragment以静态的方式,即通过在布局文件中以其它控件的方式设置时,它的生命周期随所在Activity的生命周期而发生变化。此时其生命周期的方法调用过程是这样的:

    1,当首次展示布局页面时,其生命周期方法调用的顺序是:

    2,而当关闭手机屏幕或者手机屏幕变暗时,其其生命周期方法调用的顺序是:

    3,当再次对手机屏幕解锁或者手机屏幕变亮时,其生命周期方法调用的顺序是:

    4,而当对当前Fragment所在屏幕按返回键时,其生命周期方法调用的顺序是:

    1 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onPause
    2 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onStop
    3 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onDestroyView
    4 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onDestroy
    5 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onDetach

    但是当使用FragmentManager动态的管理Fragment并且涉及到是否addToBackStack时,其生命周期的展现就略微显得有些复杂了。但是还没有复杂到无法理解。

    好,下面,我们就探究一下这些问题。

    首先,我们重写了两个Fragment,主要是重写了它们的生命周期方法,通过在其生命周期方法中打印出Log的方式来显示其方法的调用。

    两个类分别是:

    package com.yeepay.fraglifecircletest.frag;
    
    import android.app.Activity;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.yeepay.fraglifecircletest.R;
    
    public class FragA extends Fragment {
        private static final String TAG = FragA.class.getSimpleName();
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            Log.i(TAG, "onAttach");
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.i(TAG, "onCreate");
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.i(TAG, "onCreateView");
            return inflater.inflate(R.layout.fragment_test_a, null, false);
        }
    
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            Log.i(TAG, "onViewCreated");
            super.onViewCreated(view, savedInstanceState);
        }
    
        @Override
        public void onDestroy() {
            Log.i(TAG, "onDestroy");
            super.onDestroy();
        }
    
        @Override
        public void onDetach() {
            Log.i(TAG, "onDetach");
            super.onDetach();
        }
    
        @Override
        public void onDestroyView() {
            Log.i(TAG, "onDestroyView");
            super.onDestroyView();
        }
    
        @Override
        public void onStart() {
            Log.i(TAG, "onStart");
            super.onStart();
        }
    
        @Override
        public void onStop() {
            Log.i(TAG, "onStop");
            super.onStop();
        }
    
        @Override
        public void onResume() {
            Log.i(TAG, "onResume");
            super.onResume();
        }
    
        @Override
        public void onPause() {
            Log.i(TAG, "onPause");
            super.onPause();
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            Log.i(TAG, "onActivityCreated");
            super.onActivityCreated(savedInstanceState);
        }
    }
    
    FragA.java
    package com.yeepay.fraglifecircletest.frag;
    
    import android.app.Activity;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.yeepay.fraglifecircletest.R;
    
    public class FragB extends Fragment {
        private static final String TAG = FragB.class.getSimpleName();
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            Log.i(TAG, "onAttach");
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.i(TAG, "onCreate");
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.i(TAG, "onCreateView");
            return inflater.inflate(R.layout.fragment_test_b, null, false);
        }
    
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            Log.i(TAG, "onViewCreated");
            super.onViewCreated(view, savedInstanceState);
        }
    
        @Override
        public void onDestroy() {
            Log.i(TAG, "onDestroy");
            super.onDestroy();
        }
    
        @Override
        public void onDetach() {
            Log.i(TAG, "onDetach");
            super.onDetach();
        }
    
        @Override
        public void onDestroyView() {
            Log.i(TAG, "onDestroyView");
            super.onDestroyView();
        }
    
        @Override
        public void onStart() {
            Log.i(TAG, "onStart");
            super.onStart();
        }
    
        @Override
        public void onStop() {
            Log.i(TAG, "onStop");
            super.onStop();
        }
    
        @Override
        public void onResume() {
            Log.i(TAG, "onResume");
            super.onResume();
        }
    
        @Override
        public void onPause() {
            Log.i(TAG, "onPause");
            super.onPause();
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            Log.i(TAG, "onActivityCreated");
            super.onActivityCreated(savedInstanceState);
        }
    }
    
    FragB.java

    1,当我们通过以下方式添加FragA时,

    1 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    2 fragA = new FragA();
    3                     fragmentTransaction.replace(R.id.frag_container, fragA, fragNames[0]);
    4 fragmentTransaction.commit();

    它的生命周期展示方式是同在布局文件中静态设置的表现一模一样的,这里不再详细展开,大家可以查看一下以上内容。

    2,当我们以如下方式展示FragA并且没有addToBackStack时,

    @Override
        public void onClick(View v) {
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            switch (v.getId()) {
                case R.id.button1:
                    if (fragA == null) {
                        fragA = new FragA();
                        fragmentTransaction.replace(R.id.frag_container, fragA, fragNames[0]);
    //                    fragmentTransaction.addToBackStack(fragNames[0]);
                    } else {
                        Fragment fragment = fragmentManager.findFragmentByTag(fragNames[0]);
                        fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[0]);
                    }
                    break;
                case R.id.button2:
                    if (fragB == null) {
                        fragB = new FragB();
                        fragmentTransaction.replace(R.id.frag_container, fragB, fragNames[1]);
    //                    fragmentTransaction.addToBackStack(fragNames[1]);
                    } else {
                        Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);
                        fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);
                    }
                    break;
                default:
                    break;
            }
            fragmentTransaction.commit();
        }

    FragA生命周期调用顺序是:

    此时,假如再点击另外一个按钮B,将FragB展示出来,FragA和FragB的生命周期展示方式是:

    可以看到,FragA调用顺序为onPause, onStop, onDestroyView, onDestroy, onDetach.这说明,FragA已经被FragmentManager完全抛弃了,取而代之的是FragB的完全展现。而假如此时按返回键的话,FragB的生命周期也将是onPause, onStop, onDestroyView, onDestroy, onDetach。这说明,在添加Fragment时假如没有调用addToBackStack方式的话,当FragmentManager更换Fragment时,是不保存Fragment的状态的。

    3,下面我们在替换Fragment时顺便addToBackStack,则其生命周期展现方式是:

    replace FragA and addToBackStack
    ########################################################################################
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onAttach
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onCreate
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onCreateView
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onViewCreated
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onActivityCreated
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onStart
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onResume

    可以看得出来,此时的生命周期方法调用是跟没有addToBackStack时没有任何区别的。

    然后通过点击按钮B,使用FragB来替换FragA,此时FragA和FragB的生命周期方法调用顺序是:

    and then replace FragB and addToBackStack
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onPause
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onStop
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onDestroyView
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onAttach
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onCreate
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onCreateView
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onViewCreated
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onActivityCreated
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onStart
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onResume

    由此可以看出,FragA生命周期方法只是调用到了onDestroyView,而onDestroy和onDetach则没有被调用,这说明FragA的界面已经被销毁了,但是FragmentManager并没有完全销毁FragA,FragA依然有状态保存在FragmentManager里面。

    然后再点击按钮A,使用FragA来替换当前显示的FragB,此时FragA和FragB的生命周期方法调用顺序为:

    and then replace FragA again
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onPause
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onStop
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragB﹕ onDestroyView
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onCreateView
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onViewCreated
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onActivityCreated
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onStart
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onResume

    可以看到,FragB的生命方法调用顺序是跟FragB替换FragA时FragA的调用顺序一致的,作用就是只销毁了视图,但是依然保留了Fragment的状态。而此时FragA的调用则值得注意,此时FragA直接从onCreateView调起,也就是说只是重新创建了视图,而依然使用上次被替换时的Fragment状态。

    OK,说到此时,是否对Fragment的生命周期方法调用在是否addToBackStack时不同有所更加深入的了解了呢?

    好吧,最后一个问题。是关于Fragment在FragmentManager管理时,show和hide时的生命周期方法调用。

    此时的调用实现方式为:

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            switch (v.getId()) {
                case R.id.button1:
                    hideAllFrags(fragmentTransaction);
                    if (fragA == null) {
                        fragA = new FragA();
                        fragmentTransaction.add(R.id.frag_container, fragA, fragNames[0]);
                        fragmentTransaction.addToBackStack(fragNames[0]);
                    } else {
                        fragmentTransaction.show(fragA);
                    }
                    break;
                case R.id.button2:
                    hideAllFrags(fragmentTransaction);
                    if (fragB == null) {
                        fragB = new FragB();
                        fragmentTransaction.add(R.id.frag_container, fragB, fragNames[1]);
                        fragmentTransaction.addToBackStack(fragNames[1]);
                    } else {
                        fragmentTransaction.show(fragB);
                    }
                    break;
                default:
                    break;
            }
    fragmentTransaction.commit();

    细心的话可以发现,在展示Fragment时,我们使用了方法add而非上面用的replace。而且直接addToBackStack。其实这也可以理解,你想,FragmentManager在show或者hide时,肯定是已经存在的,或者假如没有的话,需要添加进来Fragment。这便是在show和hide时,需要注意的地方,即使用add和addToBackStack方法。

    在点击按钮A时,FragA的调用顺序为:

    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags﹕ hideAllFrags
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onAttach
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onCreate
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onCreateView
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onViewCreated
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onActivityCreated
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onStart
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onResume

    可以看出没有什么不同于以上所言的部分。

    然后,点击按钮B时,FragA和FragB的调用顺序为:

    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags﹕ hideAllFrags
    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onAttach
    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onCreate
    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onCreateView
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onViewCreated
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onActivityCreated
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onStart
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onResume

    可以看出,FragA并没有调用生命周期方法,这说明是展示FragB时,FragA的生命周期并没有发生变化。而FragB的生命周期与初次点击按钮A时FragA的生命周期方法相同。

    然后再继续点击按钮A和B,此时打印出来的log为:

    1 01-15 16:57:25.220    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags﹕ hideAllFrags
    2 01-15 16:57:44.990    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags﹕ hideAllFrags
    3 01-15 16:57:47.350    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags﹕ hideAllFrags
    4 01-15 16:57:48.020    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags﹕ hideAllFrags

    这说明在FragA和FragB添加进BackStack之后无论如何地show或者hide,它们的生命周期不再发生变化。

    而当屏幕上锁或变暗,然后再解锁或者变亮时,FragA和FragB的生命周期方法调用顺序为:

    when screen is locked:
    ###########################################################################################
    01-15 16:58:36.840    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onPause
    01-15 16:58:36.840    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onPause
    01-15 16:58:36.870    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onStop
    01-15 16:58:36.880    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onStop
    
    when screen is unlocked:
    ##########################################################################################
    01-15 17:05:01.850    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onStart
    01-15 17:05:01.850    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onStart
    01-15 17:05:01.870    9225-9225/com.yeepay.fraglifecircletest I/FragA﹕ onResume
    01-15 17:05:01.870    9225-9225/com.yeepay.fraglifecircletest I/FragB﹕ onResume

    可以看得出来,两个Fragment都调用了onPause, onStop, onStart, onResume。而且FragA的调用要在FragB之前,这说明跟他们添加进BackStack的顺序有关。

    以上就是我对Fragment在被FragmentManager管理时,其生命周期方法调用顺序的探究,大家觉得假如有什么地方不严谨或者不准确的地方,欢迎在留言处告知。示例工程下载地址为:FragLifeCircleTest

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    电脑屏幕不小心竖起来了?别慌,快捷键搞定

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    IT头条

    Synology 更新 ActiveProtect Manager 1.1 以增强企业网络弹性和合规性

    00:43

    新的 Rubrik Agent Cloud 加速了可信的企业 AI 代理部署

    00:34

    宇树科技 G1人形机器人,拉动一辆重达1.4吨的汽车

    00:21

    Cloudera 调查发现,96% 的企业已将 AI 集成到核心业务流程中,这表明 AI 已从竞争优势转变为强制性实践

    02:05

    投资者反对马斯克 1 万亿美元薪酬方案,要求重组特斯拉董事会

    01:18

    技术热点

    大型网站的 HTTPS 实践(三):基于协议和配置的优化

    ubuntu下右键菜单添加新建word、excel文档等快捷方式

    Sublime Text 简明教程

    用户定义SQL Server函数的描述

    怎么在windows 7开始菜单中添加下载选项?

    SQL Server 2016将有哪些功能改进?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。