错误膨胀类片段 - 重复id / illegalargumentexception?

时间:2013-03-22 03:49:53

标签: android android-fragments android-listfragment

我正在尝试创建一个我正在构建的应用程序从主要活动中获取搜索词,返回结果,然后使结果可以被点击,以便可以从每个结果中查看详细信息。我这样做是通过使用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

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

7 个答案:

答案 0 :(得分:38)

问题是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错误。

答案 1 :(得分:36)

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

    // ...

}

和瞧! :)

答案 2 :(得分:10)

让我们试一试。 我遇到了同样的问题,我使用这段代码修复了我的问题。

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

答案 3 :(得分:2)

如果您正在阅读其他答案,感觉它们看似正确,请查看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

答案 4 :(得分:2)

您可以从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();
    }
}

答案 5 :(得分:0)

这一行

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创建一个视图。您需要弄清楚这是如何发生的。

答案 6 :(得分:0)

我有两次调用片段的问题,第二次崩溃。解决方案是在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();
    }
}