关闭

不同方式切换Fragment时,生命周期的回调的不同

2641人阅读 评论(2) 收藏 举报
分类:

先上张Fragment 生命周期图

这里写图片描述

下面开始通过不同的Fragment的切换方式来分别说明生命周期的调用

  1. 通过add hide show 方式来切换Fragment
切换方法使用:
@Override
    public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
        mFragmentTransaction = getSupportFragmentManager().beginTransaction();//每次切换Fragment 都需要获取一次新的,transaction不能重复调用,要重新实例transaction
        hideFragment(mFragmentTransaction);
        switch (checkedId) {
            case R.id.rb_fragment1:
                if (fragment1 == null) {
                    fragment1 = new Fragment1();
                    mFragmentTransaction.add(R.id.rl_content, fragment1);
                } else {
                    mFragmentTransaction.show(fragment1);
                }
                mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                break;
            case R.id.rb_fragment2:
                if (fragment2 == null) {
                    fragment2 = new Fragment2();
                    mFragmentTransaction.add(R.id.rl_content, fragment2);
                } else {
                    mFragmentTransaction.show(fragment2);
                }

                mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                break;
        }
        mFragmentTransaction.commit();
    }

    /**
     * 隐藏界面
     *
     * @param transaction
     */
    private void hideFragment(FragmentTransaction transaction) {
        if (fragment1 != null) {
            transaction.hide(fragment1);
        }
        if (fragment2 != null) {
            transaction.hide(fragment2);
        }
    }
这种方式切换时的生命周期

载入Fragment1
Fragment1 onCreate
Fragment1 onCreateView
Fragment1 onStart
Fragment1 onResume
切换Fragment2:
(Fragment1不走任何生命周期,但会调onHiddenChanged方法)
Fragment2 onCreate
Fragment2 onCreateView
Fragment2 onStart
Fragment2 onResume
回到Fragment1:
(Fragment2不走任何生命周期,但会调onHiddenChanged方法)
总结:用这种方法切换,Fragment在隐藏时并不会走onDestoryView,所以显示时也不会走onCreateView,所有View都一直保存在内存中。

  1. 通过replace 方式来切换Fragment
切换方法使用:
 @Override
    public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
        mFragmentTransaction = getSupportFragmentManager().beginTransaction();//每次切换Fragment 都需要获取一次新的,transaction不能重复调用,要重新实例transaction
        switch (checkedId) {
            case R.id.rb_fragment1:
                if (fragment1 == null) {
                    fragment1 = new Fragment1();
                }
                mFragmentTransaction.replace(R.id.rl_content, fragment1);
                mFragmentTransaction.addToBackStack(null);
                mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                break;
            case R.id.rb_fragment2:
                if (fragment2 == null) {
                    fragment2 = new Fragment2();
                }
                mFragmentTransaction.replace(R.id.rl_content, fragment2);
                mFragmentTransaction.addToBackStack(null);
                mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                break;
        }
        mFragmentTransaction.commit();
    }

载入Fragment1生命周期与上面相同:
Fragment1 onCreate
Fragment1 onCreateView
Fragment1 onStart
Fragment1 onResume
切到Fragment2:
这次的Fragment1走生命周期了
Fragment1 onPause
Fragment1 onStop
Fragment1 onDestoryView
Fragment1 onDestory
Fragment2 onCreate
Fragment2 onCreateView
Fragment2 onStart
Fragment2 onResume
真实打印出来Fragment1走了onDestory,被完全回收了!
再切回到Fragment1
Fragment1 onCreate
Fragment1 onCreateView
Fragment1 onStart
Fragment1 onResume
Fragment2 onPause
Fragment2 onStop
Fragment2 onDestoryView
Fragment2 onDestory
Fragment1因为已经被回收,又走onCreate,Fragment2被回收。
3. 通过ViewPager 方式来切换Fragment
ViewPager中的Fragment 都会提前初始化
以三个Fragment 的为例来说三个Fragment会提前初始化,初始化view,这样也是用户体验很好的,先预加载view,然后再加载数据
初始化时的生命周期:
D/FragmentA: onCreate
D/FragmentA: onCreateView
D/FragmentB: onCreate
D/FragmentB: onCreateView
D/FragmentC: onCreate
D/FragmentC: onCreateView
切换到FragmentB:
(不走任何生命周期,只会调用setUserVisibleHint方法)
D/FragmentB: setUserVisibleHint
切换到FragmentC:
(不走任何生命周期,只会调用setUserVisibleHint方法)
D/FragmentC: setUserVisibleHint
再切回去也是这样
如此一来我们可以通过此方法判断是否为显示状态
注意:但是setUserVisibleHint方法只有在切换的时候调用,但是第一个fragment第一个显示的时候是不调用这个方法,所以需要注意的是第一个要显示的Fragmet需要做处理

/**
 * 第一个fragemnt要做处理,调用第一个fragment setUserVisibleHint(true); 方法,因为setUserVisibleHint(true);方法只有切换的时候才会调用,所以初始化时,要让第一个先显示,
 * 但是setUserVisibleHint会优先onCreate 方法只想,这样会有空指针问题,所以使用标记记住是否初始化完成,完成后再请求数据
 * @param savedInstanceState
 */
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    setUserVisibleHint(true);
    super.onActivityCreated(savedInstanceState);
}
```我们通过主动调用setUserVisibleHint来控制第一次不会调用setUserVisibleHint方法的问题,但是setUserVisibleHint方法会优先onCreateView方法调用,当onCreateView方法调用后还会再调用一次setUserVisibleHint方法,这时我们要对是否调用了onCreateView方法进行标记判断





<div class="se-preview-section-delimiter"></div>

/**
* 标志位,标志已经初始化完成
*/
private boolean isPrepared;

/**
* 第一个fragemnt要做处理,调用第一个fragment setUserVisibleHint(true); 方法,因为setUserVisibleHint(true);方法只有切换的时候才会调用,所以初始化时,要让第一个先显示,
* 但是setUserVisibleHint会优先onCreate 方法只想,这样会有空指针问题,所以使用标记记住是否初始化完成,完成后再请求数据
* @param savedInstanceState
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
setUserVisibleHint(true);
super.onActivityCreated(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_a, container, false);
isPrepared = true;//已经初始化
Log.d(this.getClass().getSimpleName(), “onCreateView”);
return view;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);

if (isPrepared && isVisibleToUser) {//可见的并且是初始化之后才加载
Log.d(this.getClass().getSimpleName(), "请求数据");
}

}
“`

/**
 * 标志位,标志已经初始化完成
 */
private boolean isPrepared;


/**
 * 第一个fragemnt要做处理,调用第一个fragment setUserVisibleHint(true); 方法,因为setUserVisibleHint(true);方法只有切换的时候才会调用,所以初始化时,要让第一个先显示,
 * 但是setUserVisibleHint会优先onCreate 方法只想,这样会有空指针问题,所以使用标记记住是否初始化完成,完成后再请求数据
 * @param savedInstanceState
 */
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    setUserVisibleHint(true);
    super.onActivityCreated(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_a, container, false);
    isPrepared = true;//已经初始化
    Log.d(this.getClass().getSimpleName(), "onCreateView");
    return view;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isPrepared && isVisibleToUser) {//可见的并且是初始化之后才加载
    Log.d(this.getClass().getSimpleName(), "请求数据");
    }
}

代码地址:https://github.com/jiangshujing/FragmentDemo.git

0
0

猜你在找
【套餐】Hadoop生态系统零基础入门
【套餐】嵌入式Linux C编程基础
【套餐】2017软考系统集成项目——任铄
【套餐】Android 5.x顶级视频课程——李宁
【套餐】深度学习入门视频课程——唐宇迪
【直播】广义线性模型及其应用——李科
【直播】从0到1 区块链的概念到实践
【直播】计算机视觉原理及实战——屈教授
【直播】机器学习之凸优化——马博士
【直播】机器学习&数据挖掘7周实训--韦玮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6623次
    • 积分:249
    • 等级:
    • 排名:千里之外
    • 原创:18篇
    • 转载:0篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论