为了账号安全,请及时绑定邮箱和手机立即绑定

Fragment内添加Fragment

标签:
Android

场景:Activity添加Fragment很简单,但如果我想在一个Fragment内添加另一个Fragment,又用不到ViewPager时,该咋办?

思路:参照FragmentPagerAdapter的初始化instantiate方法,全程离不开FragmentManager 

先定一个准确查找Fragment对象的规则,FragmentPagerAdapter原码:

[代码]java代码:

?

private static String makeFragmentName(int viewId, long id) { 
     return "android:switcher:" + viewId + ":" + id; 
}

FragmentPagerAdapter中的调用方式:

instantiateItem(ViewGroup container, int position)初始化方法内:

[代码]java代码:

?

long itemId = this.getItemId(position);
String name = makeFragmentName(container.getId(), itemId);

本质就是根据父类view及对应position构造一个标记

我们来写一个简单点的:

[代码]java代码:

?

private String makeFragmentName(int viewId) {
       return String.valueOf(viewId);
   }

由于我们只有一个父类控件,而且我们要做的就是在这个父类上增加一个Fragment,这样我们就可以用这个父类layout来构造一个标记,用它来找我们已经添加过的Fragment

  

[代码]java代码:

?

Fragment instantiateFragment(ViewGroup container, FragmentManager fm) {
        if (fm == null)
            return null;
        FragmentTransaction curTransaction = fm.beginTransaction();//开启事物
 
        String name = makeFragmentName(container.getId());//根据制定好的规则查找对应Fragment对象
        Fragment fragment = fm.findFragmentByTag(name);
        if(curTransaction==null)
            return null;
        if (fragment != null) {
            curTransaction.attach(fragment);//链接
        } else {
            if (mFragment == null) {
                mFragment = new Fragment ();
            }
            fragment = mFragment ;
 
            curTransaction.add(container.getId(), fragment,name);//此时还没有数据传递,先添加到队列中
        }
        if(fragment instanceof MyFragment ){//无论是根据规则查找到的还是新生成的Fragment,都要在获取对象之后传递数据
     <span class="Apple-tab-span" style="white-space:pre">      </span>Bundle bundle = new Bundle();
            fragment.setArguments(bundle);//Fragment之间的通信方式之一:向Fragment传值只能用setArguments的方法,而非Activity传统的Intent
        }
        if(curTransaction != null) {
         curTransaction.commitAllowingStateLoss();//这里参照原码实现。如果觉得丢失状态没关系可以用这个,如果在意状态,并已经处理好状态逻辑,就可以用commit
         fm.executePendingTransactions();//立即执行
    setUserVisibleHint(true);<span style="font-size: 9pt; line-height: 25.2px;">//这里如果需要 对子级别Fragment的显示状态进行设置,可用setUserVisibleHint();</span>
        }
        return fragment;
    }

对应的销毁方法:

  

[代码]java代码:

?

public void destroyFragment(FragmentManager fm, Object object) {
    if (fm == null)
        return;
    FragmentTransaction curTransaction = fm.beginTransaction();
    curTransaction.detach((Fragment) object);//移除,该方法属于切掉Fragment之间的链接
}

 

到此结束。

说一下踩过的坑:

1.FragmentManager ,我们平时在Activity中添加Fragment时使用的FragmentManager 是用getSupportFragmentManager来获取,但在Fragment再增加子级别的Fragment时,就只能用getChildFragmentManager来获取了,具体原因实验一下立马见分晓。

2.已经对Fragment用过setArguments传过数据,还想在其他的时候传数据用setArguments会发生“Fragment already active”异常,关于这个异常,以后会说到。这个时候我们就可以自己来实现一个传值方法,比如Fragment.setData(Obejct),当然也有其他的方式,自行探索

3.Fragment与Activity 通信方式:Fragment生命周期onAttach方法可以获取父类Activity对象,通过该对象可以持有父类引用,而这个Activity可以实现已经定义好的接口回调,相当于把Activity转换成接口对象,由这个接口对象来调用回调方法,Activity实现的方法可以接收回传信息,关键点就在于Fragment中如何获取Activity,想明白这个点,剩下的都简单了。

4.Fragment与Fragment之间的通信方式,分两种情况:1.两个Fragment同时由Activity持有。2一个Fragment持有另一个Fragment

情况1的通信方案参考第三点,由两个Fragment各自持有的Activity对象为中间人,交换通信内容;情况2就更简单了,既然已经持有引用了,那通信还是问题么

原文链接:http://www.apkbus.com/blog-35555-60420.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消