您的位置:首页 > 其它

Exception:Duplicate id 0x7f0b00d6, tag null, or parent id 0xffffffff with another fragment

2016-08-18 23:56 495 查看
问题场景:在项目中的MineFragment中使用第三方的MsgListFragment,在销毁MineFragment的时候,抛出异常,如下:

Caused by: java.lang.IllegalArgumentException: Binary XML file line #50: Duplicate id 0x7f0b00d6, tag null, or parent id 0xffffffff with another fragment for...

堆栈信息:

08-18 22:45:47.290: E/AndroidRuntime(2113): Caused by: java.lang.IllegalArgumentException: Binary XML file line #50: Duplicate id 0x7f0b00d6, tag null, or parent id 0xffffffff with another fragment for MsgListFragment

08-18 22:45:47.290: E/AndroidRuntime(2113):     at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2293)

08-18 22:45:47.290: E/AndroidRuntime(2113):     at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)

08-18 22:45:47.290: E/AndroidRuntime(2113):     at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:168)

08-18 22:45:47.290: E/AndroidRuntime(2113):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675)

08-18 22:45:47.290: E/AndroidRuntime(2113):     ... 30 more

大致意思,在MineFragment对应xml布局中,某个id被MsgListFragment重复使用

于是,查看下FragmentManagerImpl,如下:

public View onCreateView(View parent, String name, Context context, AttributeSet attrs)
{
if (!"fragment".equals(name)) {
return null;
}

String fname = attrs.getAttributeValue(null, "class");
TypedArray a = context.obtainStyledAttributes(attrs, FragmentTag.Fragment);//<span style="color:#FF0000;">位置1</span>
if (fname == null) {
fname = a.getString(0);
}
int id = a.getResourceId(1, -1);//<span style="color:#FF0000;">位置2</span>
String tag = a.getString(2);
a.recycle();

if (!Fragment.isSupportFragmentClass(this.mHost.getContext(), fname))
{
return null;
}

int containerId = parent != null ? parent.getId() : 0;//<span style="color:#FF0000;">位置4</span>
if ((containerId == -1) && (id == -1) && (tag == null)) {
throw new IllegalArgumentException(new StringBuilder().append(attrs.getPositionDescription()).append(": Must specify unique android:id, android:tag, or have a parent with an id for ").append(fname).toString());
}

Fragment fragment = id != -1 ? findFragmentById(id) : null;//<span style="color:#FF0000;">关键,位置5</span>
if ((fragment == null) && (tag != null)) {
fragment = findFragmentByTag(tag);
}
if ((fragment == null) && (containerId != -1)) {
fragment = findFragmentById(containerId);
}

if (DEBUG) Log.v("FragmentManager", new StringBuilder().append("onCreateView: id=0x").append(Integer.toHexString(id)).append(" fname=").append(fname).append(" existing=").append(fragment).toString());

if (fragment == null) {//<span style="color:#FF0000;">位置6</span>
fragment = Fragment.instantiate(context, fname);
fragment.mFromLayout = true;
fragment.mFragmentId = (id != 0 ? id : containerId);
fragment.mContainerId = containerId;
fragment.mTag = tag;
fragment.mInLayout = true;
fragment.mFragmentManager = this;
fragment.mHost = this.mHost;
fragment.onInflate(this.mHost.getContext(), attrs, fragment.mSavedFragmentState);
addFragment(fragment, true);
} else {//<span style="color:#FF0000;">位置7</span>
if (fragment.mInLayout)
{//<span style="color:#FF0000;">异常出现</span>
throw new IllegalArgumentException(new StringBuilder().append(attrs.getPositionDescription()).append(": Duplicate id 0x").append(Integer.toHexString(id)).append(", tag ").append(tag).append(", or parent id 0x").append(Integer.toHexString(containerId)).append(" with another fragment for ").append(fname).toString());
}

fragment.mInLayout = true;
fragment.mHost = this.mHost;

if (!fragment.mRetaining) {
fragment.onInflate(this.mHost.getContext(), attrs, fragment.mSavedFragmentState);
}

}

if ((this.mCurState < 1) && (fragment.mFromLayout))
moveToState(fragment, 1, 0, 0, false);
else {
moveToState(fragment);
}

if (fragment.mView == null) {
throw new IllegalStateException(new StringBuilder().append("Fragment ").append(fname).append(" did not create a view.").toString());
}

if (id != 0) {
fragment.mView.setId(id);
}
if (fragment.mView.getTag() == null) {
fragment.mView.setTag(tag);
}
return fragment.mView;
}


位置1:初始化内置属性等,得到TypeArray

位置2:获取资源id,tag,同时获得 id > -1

位置4:判断containerId

位置5:初步断定,执行findFragmentById方法后,fragment不为null

位置6、7:执行位置7,抛出异常

public Fragment findFragmentById(int id) {
if (this.mAdded != null)
{
for (int i = this.mAdded.size() - 1; i >= 0; i--) {
Fragment f = (Fragment)this.mAdded.get(i);
if ((f != null) && (f.mFragmentId == id)) {//<span style="color:#FF0000;">位置8</span>
return f;
}
}
}
if (this.mActive != null)
{
for (int i = this.mActive.size() - 1; i >= 0; i--) {
Fragment f = (Fragment)this.mActive.get(i);
if ((f != null) && (f.mFragmentId == id)) {
return f;
}
}
}
return null;
}
位置8:遍历mAdded,判断id是否与各个frament对应mFragmentId相等,相等,即找到对应fragment

接下来,看下mAdded是何方神圣,如下:

public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (this.mAdded == null) {
this.mAdded = new ArrayList();//<span style="color:#FF0000;">位置9</span>
}
if (DEBUG) Log.v("FragmentManager", new StringBuilder().append("add: ").append(fragment).toString());
makeActive(fragment);
if (!fragment.mDetached) {
if (this.mAdded.contains(fragment)) {
throw new IllegalStateException(new StringBuilder().append("Fragment already added: ").append(fragment).toString());
}
this.mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
if ((fragment.mHasMenu) && (fragment.mMenuVisible)) {
this.mNeedMenuInvalidate = true;
}
if (moveToStateNow)
moveToState(fragment);
}
}


位置9:可知,mAdded是个容器,专门存放创建成功的Fragment,也就是说,当Fragment创建后,addFragment方法被调用

解决方案:

@Override
public void onDestroyView() {
MsgListFragment  fragment = (MsgListFragment) getChildFragmentManager().findFragmentById(R.id.msg_list);
if(fragment != null){
getFragmentManager()
4000
.beginTransaction().remove(fragment).commit();
}
super.onDestroyView();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐