【问题标题】:Error inflating class fragment - duplicate id/illegalargumentexception?膨胀类片段时出错 - 重复 id/illegalargumentexception?
【发布时间】:2013-03-22 03:49:52
【问题描述】:

我正在尝试制作我正在构建的应用程序,从主要活动中获取搜索词,返回结果,然后让结果可点击,以便可以从每个结果中查看详细信息。我通过使用 MainActivity、ResultsActivity 和 PlaceActivity,然后使用 ListFragmentClickable(扩展 ListFragment)来做到这一点。如果手机以纵向模式定向,则结果列表应该是可见的,只有在单击结果时才能查看详细信息。如果手机是横向的,则在选择项目时,应将一个详细信息窗口弹出到列表的右侧。

在运行时,我收到一条错误消息,内容为“错误膨胀类片段”。我不知道是什么原因造成的,我很想帮助摆脱它。

我的 ListFragmentClickables 被我的 ResultsActivity 调用,它在这里:

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);
    }
}

}

这是 ListFragmentClickable 类:

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!!
  }
}

这是我的 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> 

最后是日志:

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

非常感谢任何和所有帮助。如果还有什么可以补充的,请告诉我?

【问题讨论】:

标签: android android-fragments android-listfragment


【解决方案1】:

问题是 xml 上的片段被加载了两次,第二次将其添加到 FragmentManager 时会收到 IllegalArgumentException。我昨天遇到了同样的问题。

我的解决方案,我将其更改为动态重新创建片段,而不是在 xml 文件中定义它:

更改此 xml 文件部分:

<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>

改为:

<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" />

然后在 onCreate 中,你应该将 FrameLayout 替换为一个新片段:

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

然后你会得到相同的结果,但不会出现重复 ID 错误。

【讨论】:

  • 我认为为片段静态定义 XML 是一种可接受的设计实践吗?我很困惑。
  • @mattblang,我认为你是对的,但他的问题是两次使用具有唯一 ID 的相同 XML,所以他需要动态加载。
  • 问题不是嵌套的fragment,而是fragment id(如Zhen之前所说)。
  • 这个方法对我有用。我读过的很多文档都说只以编程方式处理片段初始化,特别是如果您一次在 2 个或更多之间切换。似乎只要片段是静态的,XML 方法就可以工作。
【解决方案2】:

在 XML 中定义片段时发生(静态):如果父片段被销毁,FragmentManager 不会管理子片段。然后,当第二次扩展 XML 时,它会中断(“重复 id”错误)。

我绕过了这个问题在父片段被销毁时手动删除 XML 片段,在父片段中使用以下代码:

@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();
}

copypasters 的注意事项:XML_FRAGMENT_ID 是 XML 中片段的 id ;)


此外,我更喜欢包装 XML 片段的新类。它简化了代码,因为您只需要从中扩展您的片段类。将此类添加到您的项目中:

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);
    }
}

然后,扩展您的 XML 片段类:

package net.treboada.mytests.fragments;

public class TestXmlFragment01 extends XmlFragment {

    // ...

}

瞧! :)

【讨论】:

  • tl;dr:不要在 XML 中使用片段。
  • @Zenexer 为什么不呢?恕我直言,XML 中的片段对于与设计师合作(与编码人员合作)很有用。
  • 不就是getFragmentManager().beginTransaction().remove(this).commit(); ?
  • @dpk FragmentManager 在早期阶段无法使用。测试 null 只是避免空指针异常的预防措施。
  • 尽管如此,在使用此类之后,如果您在片段中的按钮上有一个单击侦听器,并尝试调用 YourFragment.this.getActivity().finish(),它会崩溃,因为它似乎可以没有得到活动。还不知道为什么。
【解决方案3】:

让我们试试这个。 我遇到了同样的问题,我用这段代码解决了我的问题。

 View root;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (root!= null) {
        ViewGroup parent = (ViewGroup) root.getParent();
        if (parent != null)
            parent.removeView(root);
    }
    try {
        root= inflater.inflate(R.layout.map_layout, container, false);
    } catch (InflateException e) {
        /* map is already there, just return view as it is */
    }
    return root;
}

【讨论】:

  • 一个静态视图的目的
【解决方案4】:

如果您在此处阅读其他答案并认为它们似乎是正确的,请查看此处 https://stackoverflow.com/a/19815266/1139784,因为它引用了解释如何不支持此功能的文档(至少在我的情况下,很难从这个问题中判断布局片段嵌套正在发生)

Note: You cannot inflate a layout into a fragment when that layout includes a <fragment>.
Nested fragments are only supported when added to a fragment dynamically.

更多数据在这里Best practice for nested fragments in Android 4.0, 4.1 (<4.2) without using the support library

编辑:另外,如果您正在考虑使用嵌套片段并且不需要生命周期管理,您可以创建一个自定义视图组(如扩展 LinearLayout)。 http://www.vogella.com/tutorials/AndroidCustomViews/article.html

【讨论】:

  • 谢谢!在官方 Fragment 文档中没有很好地记录此限制。这让我疯狂了一段时间......
【解决方案5】:

您可以从 XmlFragment 扩展您的片段(在 xml 中加载)。它处理父 FragmentManager 并删除自己。

public class XmlFragment extends BaseFragment {

    @Override
    public void onDestroyView() {
        Fragment parentFragment = getParentFragment();
        FragmentManager manager;
        if (parentFragment != null) {
            // If parent is another fragment, then this fragment is nested
            manager = parentFragment.getChildFragmentManager();
        } else {
            // This fragment is placed into activity
            manager = getActivity().getSupportFragmentManager();
        }
        manager.beginTransaction().remove(this).commitAllowingStateLoss();
        super.onDestroyView();
    }
}

【讨论】:

    【解决方案6】:

    两次调用片段时我遇到了同样的问题,第二次崩溃了。解决方法是在 onDetach 方法中实现 remove 语句:

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

    【讨论】:

      【解决方案7】:

      这一行

      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
      

      特别是最后的部分

      Duplicate id 0x7f070003, tag null, or parent id 0x0 with another fragment for com.example.blobtag2.ListFragmentClickable
      

      告诉您,在您的活动生命周期中的某个时刻,您正尝试为 ListFragmentClickable 创建一个视图,而该视图已经存在。您需要弄清楚这是如何发生的。

      【讨论】:

        猜你喜欢
        • 2011-09-19
        • 2013-05-28
        • 1970-01-01
        • 2014-05-19
        • 2023-03-05
        相关资源
        最近更新 更多