场景: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就更简单了,既然已经持有引用了,那通信还是问题么
共同學習,寫下你的評論
評論加載中...
作者其他優質文章