Fragment相关

第五大组件

优点:
  • 模块化(Modularity):我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中。各个布局进行解耦,方便管理
    
  • 可重用(Reusability):多个Activity可以重用一个Fragment。
    
  • 可适配(Adaptability):根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,这样用户体验更好。
    
  • Fragment是Android 3.0 (Honeycomb)被引入的。主要目的是为了给大屏幕(如平板电脑)上更加动态和灵活的UI设计提供支持。由于平板电脑的屏幕比手机的屏幕大很多,因此可用于组合和交换的UI组件的空间更大,利用Fragment实现此类设计的时,就无需管理对视图层次结构的复杂更改。
    
  • Fragment有自己的生命周期,方便管理,很容易进行增删操作
    

生命周期

onAttch--onCreate--onCreateView--onViewCrated--onActivityCreated
--onStart--onResume--onPause--onStop--onDestoryView--onDestory--onDetach

FragmentPagerAdapter和FragmentStatePagerAdapter的区别

FragmentPagerAdapter:

适用于页面较少的情况,写死的三四个左右页面可以。
destoryItem调用了detach,只是断开了2个“连接”(分离)

FragmentStatePagerAdapter:

适用于页面较多的情况,动态控制页面数量,且达到6个以上的。
destoryItem方法中有removeFragment,释放了Fragment内存

与Activity的通信:

  • Fragment调用Activity方法getActivity
  • 传入接口
  • Activity传入Handler,Fragment用Handler发送消息
  • 使用EventBus或BroadCast

Fragment与Fragment通信:

  • Fragment中调用Fragment中的方法findFragmentById
  • 使用EventBus或BroadCast

懒加载

TODO 一篇文章看懂Fragment

Activity与Fragment联系

每个Fragment由FragmentManager栈来管理,每一个Activity会有
一个FragmentManager。同一个Activity中只能有一个ID或者TAG标识
Fragment实例。Activity中有个Fragment栈,Activity销毁了,Fragment
可能还保存在栈中,缓存方便下次使用

常见坑

1.getActivity()为null

系统内存不足要把app回收之前,系统会把Activity的状态保存下来,Actvity的FragmentManager负责把Activity中的Fragment保存起来。在“内存重启”后,Activity的恢复是从栈顶逐步恢复,Fragment会在宿主Activity的onCreate方法调用后紧接着恢复。

解决方法(“安全做法”):

不使用getActivity获取context,在onAttach获取Activity,让Fragment保存Activity引用,即使Activity不在了,Fragment还是会保存Activity引用

protected Activity mActivity;
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    this.mActivity = (Activity)context;
}

2.异常:Can not perform this action after onSaveInstanceState

https://www.jianshu.com/p/d9143a92ad94

数据恢复

Fragment数据恢复:
    Fragment调用了onDestoryView方法并不代表它为null,只是回调了里面的方法而已。
    
Fragment在Activity中的数据恢复

    /**
 * 初始化Fragment
 */
private void initFragment(Bundle savedInstanceState) {
    //无缓存情况,则正常创建,add到FragmentManager中
    if (savedInstanceState == null) {
        //Fragment事务初始化
        getSupportFragmentManager().beginTransaction()
                .add(R.id.layout_container, mFragments[INDEX_WORK], 
                .show(mFragments[INDEX_WORK])
                .addToBackStack(null)
                .commitAllowingStateLoss();
    } else {//有缓存情况:取出来重新引用
        mFragments[INDEX_WORK] = getSupportFragmentManager().findFragmentByTag(WorkBenchFragment
        //取出当前选中,onSaveIntanceState中要保存该字段
        mCurrentIndex = savedInstanceState.getInt(TAB_INDEX, INDEX_WORK);
        }
    //设置选中
    selectFragment(mCurrentIndex);
}




Fragment在ViewPager中的数据恢复:

FragmentManager childFragmentManager = getChildFragmentManager();
    List cacheFragmentList = childFragmentManager.getFragments();
    if (cacheFragmentList == null || cacheFragmentList.size() <= 0) {
        //无缓存 则创建
        distributedFragment = DistributedListFragment.newInstance();
        centralizedFragment = CentralizedListFragment.newInstance();
        fragments.add(distributedFragment);
        fragments.add(centralizedFragment);
    } else {
        //有缓存 则取缓存
        for (Fragment tempFragment : cacheFragmentList) {
            if (tempFragment instanceof DistributedListFragment) {
                distributedFragment = (DistributedListFragment) tempFragment;
            }
            if (tempFragment instanceof CentralizedListFragment) {
                centralizedFragment = (CentralizedListFragment) tempFragment;
            }
            fragments.add(tempFragment);
        }

    }

Fragment重叠问题

原因:由于系统内存不足,Activity被回收,Fragment实例并没有被回收,
    当 Activity 通过导航再次被重建时,之前被实例化过的 Fragment 依然会出现在 Activity,由于代码问题,又重新new了Fragment,此时的 FragmentTransaction 中的相当于又再次 add 了 fragment 进去的,hide()和show()方法对之前保存的fragment已经失效了,所以就出现了重叠。 

解决方法:
    1.上面已写出,find出来重新引用
    2.复写Activity的onAttachFragment(Fragment fragment)方法
        
        @Override
public void onAttachFragment(Fragment fragment) {
    if (tab1 == null && fragment instanceof Tab1Fragment)
        tab1 = fragment;
    if (tab2 == null && fragment instanceof Tab2Fragment)
        tab2 = fragment;
    if (tab3 == null && fragment instanceof Tab3Fragment)
        tab3 = fragment;
    if (tab4 == null && fragment instanceof Tab4Fragment)
        tab4 = fragment;
}

判断一个Fragment是否安全(一般处理异步操作处理)

/**
 * 判断当前fragment是否安全
 *
 * @return true or false
 */
protected boolean isSafe() {
    return !(this.isRemoving() || this.getActivity() == null || this.isDetached() || !this.isAdded() || this.getView() == null);
}

ps:

1.相关Fragment中最好也要在当前onSaveInstance中保存传过来的数据
2.网络请求回调返回要判断Fragment是否attach到Activity中,否则return,因为Acitivity的onDestory方法调用时间不确定(一些取消请求放在里面了)

你可能感兴趣的:(Fragment相关)