Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error inflating class fragment - duplicate id/illegalargumentexception?

I'm trying make an app that I'm building take a search term from the main activity, return results, and then have the results be clickable such that a detail could be viewed from each results. I'm doing this by using a MainActivity, a ResultsActivity, and PlaceActivity and then a ListFragmentClickable (which extends ListFragment). If the handset is oriented in portrait mode, the results list should be viewable, with the details being viewed only if a result is clicked. If the handset is landscape, a detail window should pop up to the right of the list when an item is selected.

At runtime, I get an error that reads "error inflating class fragment". I have no idea what is causing it, and I'd love help in getting rid of it.

My ListFragmentClickables are called by my ResultsActivity, which is here:

public class ResultsActivity extends FragmentActivity implements ListFragmentClickable.OnItemSelectedListener{  private ArrayAdapter<String> mAdapter;  @Override public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_results_view);      //Receive searchTerm from MainActivity     Intent intent = getIntent();     String searchTerm = intent.getStringExtra(MainActivity.SEARCH_TERM);      mAdapter = new ArrayAdapter<String>(this, R.layout.item_label_list);      FragmentManager     fm = getSupportFragmentManager();     FragmentTransaction ft = fm.beginTransaction();      FactualResponderFragment responder = (FactualResponderFragment) fm.findFragmentByTag("RESTResponder");     if (responder == null) {         responder = new FactualResponderFragment();         ft.add(responder, "RESTResponder");     }      Bundle bundle = new Bundle();     bundle.putString("search_term", searchTerm);     responder.setArguments(bundle);      ft.commit(); }  public ArrayAdapter<String> getArrayAdapter() {     return mAdapter; }  @Override //creates a DetailFragment when a list item is selected public void onItemSelected(String link) {     DetailFragment fragment = (DetailFragment) getSupportFragmentManager().findFragmentById(R.id.detailFragment);     if (fragment != null && fragment.isInLayout()) {           fragment.setText(link);     } else {       Intent intent = new Intent(getApplicationContext(), PlaceActivity.class);           intent.putExtra(PlaceActivity.EXTRA_URL, link);       startActivity(intent);     } } 

}

Here's the ListFragmentClickable class:

public class ListFragmentClickable extends ListFragment{    private OnItemSelectedListener listener;     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.activity_results_view, container, false);       return view;   }    @Override       public void onListItemClick(ListView l, View v, int position, long id) {           updateDetail(); //see bottom       }    public interface OnItemSelectedListener {       public void onItemSelected(String link);   }    @Override   public void onAttach(Activity activity) {       super.onAttach(activity);       if (activity instanceof OnItemSelectedListener) {           listener = (OnItemSelectedListener) activity;       } else {           throw new ClassCastException(activity.toString()             + " must implemenet ListFragmentClickable.OnItemSelectedListener");       }   }    public void updateDetail() {         // Create fake data     String newTime = String.valueOf(System.currentTimeMillis());     // Send data to Activity     listener.onItemSelected(newTime); //should direct PlaceActivity!!   } } 

Here's my layout file for the ResultsActivity (activity_results_activity.xml):

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="horizontal" >  <fragment     android:id="@+id/fragment_content"     android:layout_width="0dp"     android:layout_weight="1"     android:layout_height="match_parent"     android:layout_marginTop="?android:attr/actionBarSize"     class="com.example.blobtag2.ListFragmentClickable" ></fragment>   <ListView     android:id="@android:id/list"     android:layout_width="fill_parent"     android:layout_height="50dp"     android:divider="#b5b5b5"     android:dividerHeight="1dp"></ListView>  </LinearLayout>  

And finally here's the log:

03-21 22:32:03.297: E/AndroidRuntime(764): FATAL EXCEPTION: main 03-21 22:32:03.297: E/AndroidRuntime(764): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.blobtag2/com.example.blobtag2.ResultsActivity}: android.view.InflateException: Binary XML file line #7: Error inflating class fragment 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.ActivityThread.access$600(ActivityThread.java:130) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.os.Handler.dispatchMessage(Handler.java:99) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.os.Looper.loop(Looper.java:137) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.ActivityThread.main(ActivityThread.java:4745) 03-21 22:32:03.297: E/AndroidRuntime(764):  at java.lang.reflect.Method.invokeNative(Native Method) 03-21 22:32:03.297: E/AndroidRuntime(764):  at java.lang.reflect.Method.invoke(Method.java:511) 03-21 22:32:03.297: E/AndroidRuntime(764):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 03-21 22:32:03.297: E/AndroidRuntime(764):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 03-21 22:32:03.297: E/AndroidRuntime(764):  at dalvik.system.NativeStart.main(Native Method) 03-21 22:32:03.297: E/AndroidRuntime(764): Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class fragment 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 03-21 22:32:03.297: E/AndroidRuntime(764):  at com.example.blobtag2.ListFragmentClickable.onCreateView(ListFragmentClickable.java:32) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:846) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1061) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1160) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:272) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 03-21 22:32:03.297: E/AndroidRuntime(764):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:256) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.Activity.setContentView(Activity.java:1867) 03-21 22:32:03.297: E/AndroidRuntime(764):  at com.example.blobtag2.ResultsActivity.onCreate(ResultsActivity.java:37) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.Activity.performCreate(Activity.java:5008) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 03-21 22:32:03.297: E/AndroidRuntime(764):  ... 11 more 03-21 22:32:03.297: E/AndroidRuntime(764): Caused by: java.lang.IllegalArgumentException: Binary XML file line #7: Duplicate id 0x7f070003, tag null, or parent id 0x0 with another fragment for com.example.blobtag2.ListFragmentClickable 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:277) 03-21 22:32:03.297: E/AndroidRuntime(764):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) 03-21 22:32:03.297: E/AndroidRuntime(764):  ... 30 more 

Any and all help is greatly, greatly appreciated. Please let me know if there's anything else I can add?

like image 238
user2163853 Avatar asked Mar 22 '13 03:03

user2163853


2 Answers

The problem is the fragment on xml is loaded twice, and the second time it is added to the FragmentManager you get a IllegalArgumentException. I got the same problem yesterday.

My solution, I change it to re-create the fragment dynamically instead of define it on the xml file:

Change this xml file part:

<fragment     android:id="@+id/fragment_content"     android:layout_width="0dp"     android:layout_weight="1"     android:layout_height="match_parent"     android:layout_marginTop="?android:attr/actionBarSize"     class="com.example.blobtag2.ListFragmentClickable" ></fragment> 

To this instead:

<FrameLayout     android:id="@+id/fragment_content"     android:layout_width="0dp"     android:layout_weight="1"     android:layout_height="match_parent"     android:layout_marginTop="?android:attr/actionBarSize" /> 

An then in the onCreate, yo should replace FrameLayout for a new fragment:

Fragment fragment = new ListFragmentClickable(); FragmentManager     fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.replace(R.id.fragment_content, fragment); ft.commit();  

And then you have the same but, you won't get a Duplicate ID error.

like image 196
Zhen Avatar answered Oct 29 '22 15:10

Zhen


It occurs when fragments are defined in XML (statically): FragmentManager doesn't manage child fragments if parent fragment is destroyed. Then, it breaks ("duplicate id" error) when the XML is inflated for the second time.

I bypass this problem removing the XML fragment manually when parent is destroyed, with this code in the parent fragment:

@Override public void onDestroyView() {      FragmentManager fm = getFragmentManager();      Fragment xmlFragment = fm.findFragmentById(R.id.XML_FRAGMENT_ID);     if (xmlFragment != null) {         fm.beginTransaction().remove(xmlFragment).commit();     }      super.onDestroyView(); } 

Note for copypasters: XML_FRAGMENT_ID is the id of the fragment in the XML ;)


Furthermore, I prefer a new class that wraps XML fragments. It simplyfies the code since you just need to extend your fragment class from it. Add this class to your project:

package net.treboada.mytests.fragments;  import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.util.AttributeSet;  public class XmlFragment extends Fragment {      @Override     public void onInflate(Activity activity, AttributeSet attrs,             Bundle savedInstanceState) {          FragmentManager fm = getFragmentManager();         if (fm != null) {             fm.beginTransaction().remove(this).commit();         }          super.onInflate(activity, attrs, savedInstanceState);     } } 

Then, extend your XML fragment classes:

package net.treboada.mytests.fragments;  public class TestXmlFragment01 extends XmlFragment {      // ...  } 

and voilà! :)

like image 21
caligari Avatar answered Oct 29 '22 15:10

caligari