关于Fragment的那些事

Fragment是当今Android APP设计中常用的一个东西了,可以把它理解为碎片,Fragment是依附于Activity的。前面有一篇文章详细介绍说Fragment的生命周期Android中Fragment的生命周期详解

今天,主要讲讲使用Fragment时的一些其他事情。

情形一:
我们经常会拿ViewPager和Fragment一起使用。由于ViewPager默认具有预加载机制(默认会预加载当前界面的左右两个界面),所以我们在进行业务处理时需要注意这一点。当然我们可以通过重写ViewPager来取消预加载机制。注意:通过viewPager.setOffscreenPageLimit(0)是无法取消预加载机制的,查看源码便知,

    private static final int DEFAULT_OFFSCREEN_PAGES = 1;
    public void setOffscreenPageLimit(int limit) {
        if (limit < DEFAULT_OFFSCREEN_PAGES) {
            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
                    DEFAULT_OFFSCREEN_PAGES);
            limit = DEFAULT_OFFSCREEN_PAGES;
        }
        if (limit != mOffscreenPageLimit) {
            mOffscreenPageLimit = limit;
            populate();
        }
    }

情形二:
我们仍然拿ViewPager和Fragment一起使用,比如说此时一共有4个Fragment,我们进行以下设置:viewPager.setOffscreenPageLimit(3);、
此时,默认会启动时就将4个Fragment全部加载出来。
假如说4个Fragment分别叫做AFragment、BFragment、CFragment、DFragment。此时各个Fragment的生命周期的调用顺序如下:
AFragment—onAttach
AFragment—onCreate
BFragment—onAttach
BFragment—onCreate
CFragment—onAttach
CFragment—onCreate
DFragment—onAttach
DFragment—onCreate
AFragment—onCreateView
AFragment—onActivityCreated
AFragment—onStart
AFragment—onResume
BFragment—onCreateView
BFragment—onActivityCreated
CFragment—onCreateView
CFragment—onActivityCreated
DFragment—onCreateView
DFragment—onActivityCreated

假如说这4个Fragment依附的Activity叫做MainActivity,那么从MainActivity跳转到其他Activity,4个Fragment的生命周期的调用顺序如下:
AFragment—onPause
BFragment—onPause
CFragment—onPause
DFragment—onPause
AFragment—onStop
BFragment—onStop
CFragment—onStop
DFragment—onStop

再从其他Activity回到MainActivity,4个Fragment的生命周期的调用顺序如下:
AFragment—onResume
BFragment—onResume
CFragment—onResume
DFragment—onResume

注意此时进行Fragment的切换,是不会调用到onResume方法的,此时我们可以通过

public void setUserVisibleHint(boolean isVisibleToUser)

方法来进行业务处理

情形三:
进行Fragment的切换,我们一般会使用到add/replace,也可以使用show/hide。
这里,我们先来看几个概念:
1、FragmentManager
Fragment管理器
如果是在FragmentActivity中,我们可以通过getSupportFragmentManager()得到FragmentManager对象;
如果是在Activity中,我们可以通过getFragmentManager()得到FragmentManager对象;
如果是在AppCompatActivity中,我们可以通过getSupportFragment()得到FragmentManager对象;
如果是在Fragment中,我们可以通过getChildFragmentManager()得到FragmentManager对象。
2、FragmentTransaction
Fragment事务
使用FragmentTransaction时需要注意,我们在使用FragmentTransaction进行commit时,不能使用之前已经commit过的FragmentTransaction对象,而应该通过fragmentManager.beginTransaction得到一个新的FragmentTransaction对象。

下面我们先看一下,
使用add/replace。举例如下:

AFragment aFragment = new AFragment();
FragmentManager fragmentManager = getSupportFragmentManager();  //此处只是示例代码,实际在项目中根据情况做改动,比如此处可以将fragmentManager作为全局变量来声明
fragmentManager.beginTransaction().add(R.id.linear_fragment, aFragment).commit();  //R.id.linear_fragment对应的布局是存放Fragment的布局

@Override
public void onClick(View v) {
       switch (v.getId()) {
             case R.id.fragment_a:
                     AFragment aFragment = new AFragment();
                     fragmentManager.beginTransaction().replace(R.id.linear_fragment, aFragment).commit();
                     break;
             case R.id.fragment_b:
                     BFragment bFragment = new BFragment();
                     fragmentManager.beginTransaction().replace(R.id.linear_fragment, bFragment).commit();
                     break;        
       }
}

假如说AFragment和BFragment所依附的Activity叫做MainActivity,此时从MainActivity跳转至其它Activity,只有当前Fragment的onPause和onStop会被调用,当从其它Activity回到MainActivity的时候,只有当前Fragment的onResume会被调用。

使用show/hide,举例如下:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.linear_fragment, currentFragment).show(currentFragment).commit();

private void showFragment(Fragment fragment) {
      if (currentFragment != fragment) {
          FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
          fragmentTransaction.hide(currentFragment);
          currentFragment = fragment;
          if (!fragment.isAdded()) {
              fragmentTransaction.add(R.id.linear_fragment, fragment).show(fragment).commit();
          } else {
               fragmentTransaction.show(fragment).commit();
          }
      }
}

假如说我们一个有3个Fragment,分别叫做AFragment、BFragment、CFragment,这些Fragment依附的Activity叫做MainActivity,如果这些Fragment都被添加进队列,那么此时从MainActivity跳转至其它Activity,这3个Fragment的onPause、onStop都会被调用,关于调用顺序取决于Fragment被添加进队列的顺序,比如说:AFragment第一个被添加进队列,CFragment第二个被添加进队列,BFragment最后一个被添加进队列,那么此时方法执行顺序为:AFragment—onPause、CFragment—onPause、BFragment—onPause、AFragment—onStop、CFragment—onStop、BFragment—onStop。如果此时从其它Activity回到MainActivity,这3个Fragment的onResume也都会被调用,关于调用顺序同样取决于Fragment被添加进队列的顺序,还是举刚才的例子,对应的是:AFragment—onResume、CFragment—onResume、BFragment—onResume。

此时,假如说我们要实现类似于以下需求:
从AFragment切换到BFragment(此时AFragment、BFragment都已经被添加进队列了),AFragment中停止播放视频,切换回AFragment,接着播放视频,该怎么实现呢?
此时AFragment的onPause、onStop、onResume方法都不会被调用,其实此时我们可以通过onHiddenChanged这个方法来实现我们的需求,我们来看源码中对该方法的定义如下:

public void onHiddenChanged(boolean hidden) {
}

OK,最后我们再来看一下FragmentTransaction的主要方法。
一、add(id, fragment):添加fragment到队列中,并显示该fragment到指定布局中。
生命周期调用:
当fragment与activity建立连接并被创建时:
onCreateView()、onActivityCreated()、onStart()、onResume()
当fragment与activity建立连接但是未被创建时:
onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()
当fragment与activity未建立连接并且未被创建时:
onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()

二、replace(id, fragment):先检查队列中是否已经存在,存在就会崩溃,不存在就会进入队列并把其他fragment清出队列,最后显示该fragment到指定布局中。
生命周期的调用:同add(id, fragment)

三、show(fragment):显示队列中的指定fragment。
生命周期的调用:
如果之前被调用过hide(fragment),则回调onHiddenChange(boolean hidden)

四、hide(fragment):隐藏队列中指定的fragment,相当于调用视图的setVisibility(View.GONE)。
生命周期的调用:
回调onHiddenChange(boolean hidden)

五、detach(fragment):销毁指定fragment的视图,并且该fragment的onCreateView()不能再被调用(除非调用attach(fragment)重新连接)。
生命周期的调用:
回调onDestroyView()

六、attach(fragment):创建指定fragment的视图。标识该fragment的onCreateView()能被调用。
生命周期的调用:
当队列中存在该fragment时且被调用detach(fragment)时,回调onCreateView()、onActivityCreated()、onResume()。

七、addToBackStack(string):使本次事务增加的fragment进入当前activity的返回栈中。当前参数是对返回栈的描述,没有什么实际用途。传入null即可。

八、commit():提交本次事务,可在非主线程中被调用。主要用于多线程处理情况。

九、commitNow():提交本次事务,只在主线程中被调用。这时候addToBackStack(string)不可用。

注:
一、
入队的标准是:该fragment的onCreateView()被调用。
出队的标准是:该fragment的onDetach()被调用。
二、
fragment被创建时,生命周期方法回调:
onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()
销毁时(没有用到返回栈):onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()
重新返回到上一个Fragment(没有用到返回栈):onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()
销毁时(用到返回栈):onPause()、onStop()、onDestroyView()
重新返回到上一个Fragment(用到返回栈):onCreateView()、onActivityCreated()、onStart()、onResume()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值