java.lang.IllegalStateException: у указанного дочернего элемента уже есть родитель

99

Я использую фрагменты, когда создаю экземпляр фрагмента в первый раз. но во второй раз я получил это исключение. Не удалось найти строку, в которой возникла ошибка?

 04-04 08:51:54.320: E/AndroidRuntime(29713): FATAL EXCEPTION: main
    04-04 08:51:54.320: E/AndroidRuntime(29713): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addViewInner(ViewGroup.java:3013)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addView(ViewGroup.java:2902)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addView(ViewGroup.java:2859)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addView(ViewGroup.java:2839)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.NoSaveStateFrameLayout.wrap(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.BackStackRecord.run(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl$1.run(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.os.Handler.handleCallback(Handler.java:587)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.os.Handler.dispatchMessage(Handler.java:92)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.os.Looper.loop(Looper.java:132)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.app.ActivityThread.main(ActivityThread.java:4126)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at java.lang.reflect.Method.invokeNative(Native Method)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at java.lang.reflect.Method.invoke(Method.java:491)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at dalvik.system.NativeStart.main(Native Method)

Вот что я делаю, когда нажимаю на элемент фрагмента моего списка.

// If we are not currently showing a fragment for the new
 // position, we need to create and install a new one.
 RouteSearchFragment df = RouteSearchFragment.newInstance(index);

 // Execute a transaction, replacing any existing fragment
 // with this one inside the frame.
 FragmentTransaction ft = fragmentManager.beginTransaction();
 ft.replace(R.id.details_full, df);
 ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
 ft.commit();

В первый раз, когда все в порядке, я нажимаю element2 из списка, это тоже нормально; но когда я вернусь к element1, у меня возникла эта ошибка.

Спасибо всем!

Хайтем Суисси
источник
необходимо вызвать layoutView.removeAllViews (); перед добавлением видов в макет
ρяσѕρєя K
@imrankhan ошибается! Вы можете добавить, не удаляя все. Самая важная часть отсутствует, и поскольку в stacktrace нет специального пакета, я предлагаю вам удалить некоторый код и протестировать его шаг за шагом ...
УорренФэйт
1
Я добавляю подробности, вы можете это увидеть?
haythem souissi
Что это за класс RouteSearchFragment ?? Не могу найти никаких ссылок в документах Android. Пожалуйста, обновите определение класса.
noob

Ответы:

36

Когда вы переопределяете OnCreateViewв своем RouteSearchFragmentклассе, есть ли у вас

if(view != null) {
    return view; 
}

сегмент кода?

Если это так, удаление оператора return должно решить вашу проблему.

Вы можете сохранить код и вернуть представление, если вы не хотите повторно создавать данные представления, а методом onDestroyView () вы удаляете это представление из его родителя следующим образом:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null) {
                parent.removeAllViews();
            }
        }
    }
Медо
источник
5
@Override public void onDestroyView () {super.onDestroyView (); ViewGroup parentViewGroup = (ViewGroup) mRoutesSearchViewContainer.getParent (); если (null! = parentViewGroup) {parentViewGroup.removeView (mRoutesSearchViewContainer); }}
haythem souissi
@Medo: Вы можете вкратце объяснить это. У меня такая же ошибка, как и в logcat. поскольку вы сделали предложение «удалите оператор return, чтобы решить вашу проблему», но нам нужно вернуть объект View в методе onCreateView (). можете ли вы предоставить фрагмент кода для объяснения. Спасибо.
Кришна Прасад
@Krishna Просто надуйте и верните вид, как обычно. Вы можете пропустить весь оператор if.
Medo
65
Для меня мне просто пришлось заменить return inflater.inflate(R.layout.fragment_search, container);наreturn inflater.inflate(R.layout.fragment_search, container, false);
Sufian
370

Извините, что отправил на старый вопрос, но я смог исправить его, используя совершенно другое решение. Я получал это исключение, но я изменил первую строку моего переопределения onCreatView следующим образом:

View result = inflater.inflate(R.layout.customer_layout, container);

...к этому:

View result = inflater.inflate(R.layout.customer_layout, container, false);

Я понятия не имею, почему, но использование переопределения, которое принимает логическое значение, поскольку третий параметр исправил его. Я думаю, что это говорит Фрагменту и / или Деятельности не использовать «контейнер» в качестве родителя вновь созданного Представления.

Патрик
источник
53
Не сожалейте - это было очень полезно для меня и, очевидно, для ряда других людей. Спасибо!
введите коды
Большое спасибо, я все время забываю об этом и возвращаюсь к этому ответу
noloman
@Patrick, первый прикрепляет надутый вид к контейнеру, добавление флага false указывает, что вы не хотите добавлять надутый вид в контейнер.
Ne0
и я продолжаю возвращаться к этому посту и
узнаю
45

Я сталкивался с этой проблемой много раз. Добавьте следующий код для решения этой проблемы:

@Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parentViewGroup = (ViewGroup) view.getParent();
            if (parentViewGroup != null) {
                parentViewGroup.removeAllViews();
            }
        }
    }

Спасибо

Hardik
источник
Спасибо за это решение :) У меня очень конкретный случай, когда я не могу использовать надувной модуль для решения этой проблемы. Вы сэкономили мне много времени
Боян
Извините, я не совсем понимаю, потому что я новичок в Android.
Zin Win Htet 05
В view.getParent (); Откуда взялся объект обзора дозы?
Zin Win Htet 05
Cristy YG: Возьмите экземпляр View в качестве глобальной переменной и увеличьте размер XML-макета над глобальной переменной. ты следишь за мной или нет?
Hardik 01
Да, экземпляр представления объявлен как глобальный.
Hardik
35

Если у вас есть это заявление ..

View view = inflater.inflate(R.layout.fragment1, container);//may be Incorrect 

Тогда попробуйте это .. Добавьте false в качестве третьего аргумента .. Может быть, это поможет ..

View view = inflater.inflate(R.layout.fragment1, container, false);//correct one
Дхананджай М
источник
21

У меня был этот код во фрагменте, и он вылетал, если я пытаюсь вернуться к этому фрагменту

if (mRootView == null) {
    mRootView = inflater.inflate(R.layout.fragment_main, container, false);
} 

собрав ответы в этой теме, я понял, что родительский элемент mRootView по-прежнему имеет mRootView в качестве дочернего элемента. Итак, это было моим исправлением.

if (mRootView == null) {
    mRootView = inflater.inflate(R.layout.fragment_main, container, false);
} else {
    ((ViewGroup) mRootView.getParent()).removeView(mRootView);
}

надеюсь это поможет

user1736525
источник
2
+1 мне помогло. Особенно верно, если ваша активность остается, но менеджер фрагментов добавляет новые фрагменты поверх. когда он возвращается к первому фрагменту, необходимо убедиться, что старое корневое представление удалено. Спасибо!
Bundeeteddee
Это мне очень помогло. Я нахожу это решение в течение 3 дней. Простой и красивый ответ.
Zin Win Htet
Вот Это Да! наконец это сработало для меня! Решетчатый раствор. Спасибо!
avisper 05
У меня нет объяснения, почему "(ViewGroup) mRootView.getParent ()). RemoveView (mRootView);" работает в отличие от прямого вызова «<WhateverIsParentViewGroupName> .removeView (mRootView)». Но это работает и у меня, я тестирую на Android 8.0 и 9.0. Благодаря бутон ^
Хай
16

Это также происходит, когда представление, возвращаемое onCreateView (), не является представлением, которое было раздутым.

Пример:

View rootView = inflater.inflate(R.layout.my_fragment, container, false);

TextView textView = (TextView) rootView.findViewById(R.id.text_view);
textView.setText("Some text.");

return textView;

Исправить:

return rootView;

Вместо того:

return textView; // or whatever you returned
Матеус Пирес
источник
Спасибо! мне это помогло!
Судиш Мохан
5

У меня была эта проблема, и я не мог решить ее в Java-коде. Проблема была в моем xml.

Я пытался добавить textView в контейнер, но заключил textView в LinearLayout.

Это был исходный файл xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textColor="#fff"
        android:background="?android:attr/activatedBackgroundIndicator"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

</LinearLayout>

Теперь, когда LinearLayout удален:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textColor="#fff"
        android:background="?android:attr/activatedBackgroundIndicator"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

Мне это показалось незначительным, но помогло, и я вообще не изменил свой Java-код. Все это было в xml.

DroidCrafter
источник
2

Вы добавляете объект Viewв объект layout, но представление уже находится в другом layout. Представление не может находиться более чем в одном месте.

новичек
источник
Я добавил более подробную информацию к своему вопросу, вы видите это?
haythem souissi
1

Это решение может помочь:

public class FragmentItem extends Android.Support.V4.App.Fragment
{
    View rootView;
    TextView textView;

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (rootView != null) 
        {
            ViewGroup parent = (ViewGroup)rootView.Parent;
            parent.RemoveView(rootView);
        } else {
            rootView = inflater.Inflate(Resource.Layout.FragmentItem, container, false);
            textView = rootView.FindViewById<TextView>(Resource.Id.textViewDisplay);            
        }
        return rootView;
    }
}
Бхавит С. Сенгар
источник
1
Я думаю, что rootView всегда будет нулевым, поскольку вы его не инициализировали.
Zin Win Htet
rootView всегда должен быть нулевым
Thinsky
1

Я решил его, установив attachToRootв inflater.inflate()к false.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_overview, container, false);
    return view;
}
Мистер Б.
источник
0

в вашем xml файле вы должны установить layout_width и layout_height из wrap_content в match_parent. это исправлено для меня.

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Эван Нго
источник