27

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

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

我的 ResultsActivity 调用了我的 ListFragmentClickables,它位于:

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

非常感谢任何和所有帮助。请让我知道是否还有其他可以添加的内容?

4

7 回答 7

39

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

于 2013-04-12T07:24:11.267 回答
38

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

复制粘贴的注意事项: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 {

    // ...

}

瞧!:)

于 2013-12-19T15:31:10.517 回答
11

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

 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;
}
于 2013-07-02T09:40:42.243 回答
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.

此处有更多数据不使用支持库的 Android 4.0、4.1 (<4.2) 中嵌套片段的最佳实践

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

于 2014-03-19T23:56:43.617 回答
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();
    }
}
于 2015-07-30T12:05:34.417 回答
1

我在两次调用片段时遇到了同样的问题,第二次崩溃了。解决方案是在 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();
    }
}
于 2018-03-08T12:13:51.813 回答
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 创建一个视图,而该视图已经存在。您需要弄清楚这是如何发生的。

于 2013-03-22T03:59:15.873 回答