ILJMALL project过程中遇到Fragment嵌套问题:IllegalArgumentException: Binary XML file line #23: Duplicate id(示例
Posted s_x_q
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ILJMALL project过程中遇到Fragment嵌套问题:IllegalArgumentException: Binary XML file line #23: Duplicate id(示例相关的知识,希望对你有一定的参考价值。
- 出现场景:当点击“分类”再返回“首页”时,发生error退出
- BUG描述:Caused by: java.lang.IllegalArgumentException: Binary XML file line #23: Duplicate id 0x7f0d0054, tag null, or parent id 0xffffffff with another fragment for com.example.sxq123.iljmall.FragmentCatagorySpace
- //framgment_home.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text = "@string/home"/> <fragment android:id = "@+id/fragment_space" android:name = "com.example.sxq123.iljmall.FragmentCatagorySpace" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> </ScrollView> </LinearLayout>
- //FragmentHome.java
public class FragmentHome extends Fragment { private View view; FragmentCatagorySpace fragmentCatagorySpace ; @Override public View onCreateView(LayoutInflater inflater , ViewGroup container , Bundle savedInsataceState){ view = inflater.inflate(R.layout.fragment_home, null); Log.d(this.getClass().getName()," onCreateView() Begin"); initChildFragment(); return view; } private void initChildFragment(){ Log.d("-------------------","init space "); fragmentCatagorySpace = (FragmentCatagorySpace)getChildFragmentManager().findFragmentById(R.id.fragment_space); if(fragmentCatagorySpace != null){ Log.d("----------------","init space success and no null"); } } }
- 问题原因
activity中不同的frament之间项目替换的时候,FragmentManager只会remove和add这些frament,
然而这些frament里面自己加载的frament(这里就是我们的FragmentCatagorySpace)是没有被remove. 很显然这是一个缺陷!
因为后一个frament(FragmentCatagorySpace)很明显是依赖与他的父frament的,应该同时递归的remove.
那么如何解决这个问题呢!很显然就是在不用这个frament(FragmentHome)的时候把他里面加载的frament给remove掉!
这个操作在Fragment的重新onCreateView() inflate layout之前remove掉就可以解决问题了!
比如将remove的事务放在父Fragment的onDestroyView()之中执行
- 修正后的代码
public class FragmentHome extends Fragment { private View view; FragmentCatagorySpace fragmentCatagorySpace ; @Override public View onCreateView(LayoutInflater inflater , ViewGroup container , Bundle savedInsataceState){ view = inflater.inflate(R.layout.fragment_home, null); Log.d(this.getClass().getName()," onCreateView() Begin"); initChildFragment(); return view; } @Override public void onDestroyView(){ super.onDestroyView(); if(fragmentCatagorySpace != null){ Log.d("-------------------", "space no null"); FragmentManager fragmentManager = getFragmentManager(); if(fragmentManager != null && !fragmentManager.isDestroyed()){ final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction (); if(fragmentTransaction != null){ fragmentTransaction.remove(fragmentCatagorySpace).commit(); //commit()和commitAllowingStateLoss()都是先发送到主线程任务队列中, 当主线程准备好了再执行,异步。 // //如果没有在inflate之前执行remove child fragmetn 的transaction,将会发生duplicate id 的exception !!! // fragmentTransaction.commit();//可以放在onCreateView中执行commit(),但偶尔会发生onSaveInstanceState()之后不能执行commit()的冲突 fragmentTransaction.commitAllowingStateLoss(); //立即执行任务队列中的transaction, 不异步 !!!!!!!!!!!!!!!重点!!!!!!!!!!!!!!!!!!!! //防止remove事务被加到主线程任务队列中,那这样异步的话可能这些事物直到父Fragment重新执行onCreateView() //之前都没有执行完,同样会发生duplicate id 的异常 //如果这些remove 的食物放在父Fragment的onSaveInstanceState()中执行, 由于onSaveInstanceState()调用并不 //是每一个Fragment生命周期都会被调用(????),所以偶尔也会发生duplicate id 的异常 fragmentManager.executePendingTransactions(); Log.d("------------------"," space destroy"); } } } } private void initChildFragment(){ Log.d("-------------------","init space "); fragmentCatagorySpace = (FragmentCatagorySpace)getChildFragmentManager().findFragmentById(R.id.fragment_space); if(fragmentCatagorySpace != null){ Log.d("----------------","init space success and no null"); } } }
以上是关于ILJMALL project过程中遇到Fragment嵌套问题:IllegalArgumentException: Binary XML file line #23: Duplicate id(示例的主要内容,如果未能解决你的问题,请参考以下文章
project管理之makefile与自己主动创建makefile文件过程