关闭 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

    上一篇返回首页 下一篇

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

    别人在看

    帝国CMS7.5编辑器上传图片取消宽高的三种方法

    帝国cms如何自动生成缩略图的实现方法

    Windows 12即将到来,将彻底改变人机交互

    帝国CMS 7.5忘记登陆账号密码怎么办?可以phpmyadmin中重置管理员密码

    帝国CMS 7.5 后台编辑器换行,修改回车键br换行为p标签

    Windows 11 版本与 Windows 10比较,新功能一览

    Windows 11激活产品密钥收集及专业版激活方法

    如何从 Windows 11 中完全删除/卸载 OneNote?无解!

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    IT头条

    华为Pura80系列新机预热,余承东力赞其复杂光线下的视频拍摄实力

    01:28

    阿里千问3开源首战告捷:全球下载破千万,国产AI模型崛起新高度!

    01:22

    DeepSeek R1小版本试升级:网友实测编程能力已达到国际一线水平

    23:15

    NVIDIA 与 Dell 合作,大规模交付 Blackwell AI 系统

    20:52

    Cerebras 以最快的 Llama 4 Maverick 性能引领 LLM 推理竞赛

    20:51

    技术热点

    PHP中的随机性——你觉得自己幸运吗?

    搞定Ubuntu Linux下WPA无线上网

    Java使用内存映射实现大文件的上传

    MySQL安全性指南

    MySQL两项性能的基本测试浅谈

    教您使用UniqueIdentifier选取SQL Server主键

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

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