web-dev-qa-db-ja.com

クラスフラグメントの膨張エラー-重複したID /不正な引数の例外?

私が作成しているアプリをメインアクティビティから検索語句を取得して結果を返し、各結果から詳細を表示できるように結果をクリックできるようにしています。これを行うには、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

どんな助けも大いに感謝します。他に何か追加できることがあれば教えてください。

26
user2163853

問題は、xmlのフラグメントが2回ロードされ、2回目に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エラーは発生しません。

39
Zhen

発生フラグメントがXMLで定義されている場合(静的):親フラグメントが破棄された場合、FragmentManagerは子フラグメントを管理しません。次に、XMLが2度目に膨張すると、エラーが発生します(「重複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 {

    // ...

}

ほら! :)

37
caligari

これを試してみましょう。同じ問題が発生し、このコードを使用して問題を修正しました。

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

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

他の回答が正しいように思われてここで他の回答を読んでいた場合は、こちらをご覧ください 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

2
Eric Woodruff

2回呼び出されたフラグメントで同じ問題があり、2回目にクラッシュしました。解決策は、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();
    }
}
1
Helix.Algorithm

この線

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のビューがすでに存在しているときに、それを作成しようとしていることを通知しています。これがどのように発生しているかを理解する必要があります。

0
j__m