2 u012504392 u012504392 于 2016.02.04 22:05 提问

关于学习《第一行代码》中发现的问题,不敢说是错误,应该是郭霖大神笔误。麻烦各位大神来教训晚辈。。。

_第一处问题:在fragment一章里关于动态加载fragment部分中,要添加的fragment类的代码如下
public class Fragment_3 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_second_fragment, container);
return view;
}
}
###########################################################
这是按钮中的事件监听器中的FragmentTransaction里的方法:
//tran.replace(R.id.linear, frag);
tran.add(R.id.linear, frag);
这是书中原代码,它是用replace方法,可是这样我试过,会出现java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.错误,然后我按照自己的理解把上述代码中的container改成null后程序正常运行无错误,我就抱着“指定的父容器资源和container冲突了”的问号试着去寻找答案,发现FragmentTransaction的replace和add方法都是abstract方法,然后我就不知道它俩为什么会冲突了。求解决...
第二个问题:上面说道我把container改成null后程序无错了,然后我按钮的监听事件里写的是add方法,然后我一直点他就会一直添加同一个fragment,这很正常,我疑问的地方是我换成replace方法后,点击按钮也会添加一个fragment,而且再此点击没有变化(也就是只能添加一个),我的问题是,为什么他不是替换掉原有的fragment而是添加呢,而且添加还只能添加一次,而且如果replace也是添加的作用,既然add能添加了,还要replace方法有何用?
附replace方法时运行程序点击按钮后的截图:
图片说明
附add方法时运行程序点击按钮后的截图:
图片说明

5个回答

sinyu890807
sinyu890807   2016.04.21 13:35

没办法了,既然被提问了那我就来回答一下吧,虽然已经是老贴子了。
先说第一个问题,你的这个写法和《第一行代码》里要求的写法并不一样:

View view = inflater.inflate(R.layout.right_second_fragment, container);

第二个参数传入了container,这就是说明要把container设置为view的父布局,而一个view如果有了父布局,它还怎么能再被添加到另一个布局中呢?所以就会报 java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.这个错误,很好理解。
而如果改成null的话,就不给view添加父布局了,那么就不会出现错误了。而第一行代码里面要求的写法是:

View view = inflater.inflate(R.layout.right_second_fragment, container, false);

第三个参数传入false也可以正常工作,具体原因可以参考我的一篇文章 http://blog.csdn.net/guolin_blog/article/details/12921889

再来说第二个问题,接口名字的设计很大程度上就能直接反应出这个接口是用来干什么的。那么很明显,add()方法顾名思义就是用来添加的,所以你add一个Fragment,那界面上就会出现一个Fragment。类似地,replace()方法很明显就是用来替换的,你原先容器里已经有一个Fragment了,那么就会把原先的替换掉,换成你指定的新Fragment,而如果原先容器是空的,那么也会用你指定的新Fragment去填充容器,看上去就好像是add了一样,每个接口都是有它自己使用的场景的,Android不会随便加一些没有意义的接口在SDK里面。

qq_37299249
qq_37299249 为什么我在activity_main.xml 右fragment 的不写name属性,启动会停止运行,
10 个月之前 回复
aa4100123
aa4100123 郭神我爱你。
一年多之前 回复
caozhy
caozhy   Ds   Rxr 2016.02.04 22:16

指定的父容器资源和container冲突了
不是的

是子控件已经有父控件了,你又把它添加到另一个容器中,所以报错了。
R.id.linear不知道在哪里定义的,它代表一个唯一的控件id,它是替换判断的关键。

u012504392
u012504392 是啊,就是那个onCreateView方法里的container已经成为它的父控件了,后来add方法里又指定了一个父控件,R.id.linear定义在主界面的xml中,截图在下面
接近 2 年之前 回复
luochoudan
luochoudan   Ds   Rxr 2016.02.04 22:42

第一个问题在 inflater.inflate(R.layout.right_second_fragment, container);添加个false参数试试。第二个问题,replace的作用相当于remove和add的复合,明白了吧。

u012504392
u012504392 第一个问题我已经解决了,我就是把container改成了null就行了,不过书中没改。关于replace,它并没有移除任何fragment啊,截图中的绿色部分就是原先已经存在的fragment,并没有移除啊
接近 2 年之前 回复
a398613391
a398613391   2016.04.21 13:27

虽然没看到源码 但是感觉。。。。。 郭神会粗来解答的

u012504392
u012504392   2016.02.05 11:38

主Activity的xml截图:
图片说明

Csdn user default icon
上传中...
上传图片
插入图片