java.lang.IllegalStateException: Anak yang ditentukan sudah memiliki induk

99

Saya menggunakan fragmen, saat saya membuat instance fragmen untuk pertama kali. tapi kedua kalinya saya mendapat pengecualian ini. Saya tidak dapat menemukan baris di mana saya mendapatkan kesalahan?

 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)

Inilah yang saya lakukan ketika saya mengklik elemen dari fragmen daftar saya.

// 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();

Pertama kali ok, saya klik elemen2 dari daftar, juga ok; tetapi ketika saya kembali ke elemen1 saya mendapat bug ini.

Terimakasih semuanya!

haythem souissi
sumber
perlu memanggil layoutView.removeAllViews (); sebelum menambahkan tampilan ke tata letak
ρяσѕρєя K
@imrankhan salah! Anda dapat menambahkan tanpa menghapus semua. Bagian yang paling penting hilang dan karena tidak ada paket khusus di stacktrace, saya sarankan Anda menghapus beberapa kode dan mengujinya selangkah demi selangkah ...
WarrenFaith
1
Saya menambahkan lebih banyak detail, tolong dapatkah Anda melihatnya?
haythem souissi
Apa kelas RouteSearchFragment ini ?? Tidak dapat menemukan referensi apa pun di dokumen Android. Harap perbarui juga definisi kelas.
noob

Jawaban:

36

Saat Anda mengganti OnCreateViewdi RouteSearchFragmentkelas, apakah Anda memiliki

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

segmen kode?

Jika demikian, menghapus pernyataan pengembalian seharusnya menyelesaikan masalah Anda.

Anda bisa menyimpan kode dan mengembalikan tampilan jika Anda tidak ingin membuat ulang data tampilan, dan metode onDestroyView () Anda menghapus tampilan ini dari induknya seperti ini:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null) {
                parent.removeAllViews();
            }
        }
    }
Medo
sumber
5
@Override public void onDestroyView () {super.onDestroyView (); ViewGroup parentViewGroup = (ViewGroup) mRoutesSearchViewContainer.getParent (); if (null! = parentViewGroup) {parentViewGroup.removeView (mRoutesSearchViewContainer); }}
haythem souissi
@Medo: Bisakah Anda memberikan penjelasan singkat untuk ini. Saya memiliki kesalahan yang sama yang ditunjukkan di logcat. karena Anda telah memberikan saran "menghapus pernyataan pengembalian harus menyelesaikan masalah Anda" tetapi kita perlu mengembalikan objek View dalam metode onCreateView (). dapatkah Anda memberikan kode cuplikan untuk penjelasan Anda. Terima kasih.
Krishna Prasad
@Rishna Cukup memompa dan mengembalikan tampilan seperti biasa. Anda dapat melewati seluruh pernyataan if.
Medo
65
Bagi saya, saya hanya harus mengganti return inflater.inflate(R.layout.fragment_search, container);denganreturn inflater.inflate(R.layout.fragment_search, container, false);
Sufian
370

Maaf memposting ke pertanyaan lama tetapi saya dapat memperbaikinya menggunakan solusi yang sama sekali berbeda. Saya mendapatkan pengecualian ini tetapi saya mengubah baris pertama penggantian onCreatView saya dari ini:

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

...untuk ini:

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

Saya tidak tahu mengapa tetapi menggunakan override yang menerima boolean sebagai param ketiga memperbaikinya. Saya pikir ini memberitahu Fragment dan / atau Activity untuk tidak menggunakan "container" sebagai induk dari View yang baru dibuat.

Patrick
sumber
53
Jangan menyesal - ini sangat berguna bagi saya, dan jelas bagi sejumlah orang lain. Terima kasih!
masukkan kode
Terima kasih banyak, saya terus melupakan ini dan kembali ke jawaban ini
noloman
@Patrick, Yang pertama melampirkan tampilan yang digelembungkan ke penampung, menambahkan tanda palsu menentukan Anda tidak ingin menambahkan tampilan yang dipekarkan ke penampung.
Ne0
dan saya terus kembali ke posting ini dan menemukan bahwa ini JAWABANNYA :)
noloman
45

Saya telah menghadapi masalah ini berkali-kali. Harap tambahkan kode berikut untuk mengatasi masalah ini:

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

Terima kasih

Hardik
sumber
Terima kasih atas solusi ini :) Saya memiliki kasus yang sangat spesifik di mana saya tidak dapat menggunakan inflater untuk menyelesaikannya. Anda menghemat banyak waktu saya
Bojan
Maaf, saya tidak begitu mengerti karena saya baru mengenal android.
Zin Win Htet
Dalam view.getParent (); Dari mana objek tampilan dosis berasal?
Zin Win Htet
Cristy YG: Ambil contoh View sebagai variabel global, dan perbesar layout xml Anda pada variabel global di atas. apakah kamu mengikuti saya atau tidak?
Hardik
Ya, lihat instance yang dideklarasikan sebagai global.
Hardik
35

Jika Anda memiliki pernyataan ini ..

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

Kalau begitu coba ini .. Tambahkan salah sebagai argumen ketiga .. Semoga bisa membantu ..

View view = inflater.inflate(R.layout.fragment1, container, false);//correct one
Dhananjay M
sumber
21

Saya memiliki kode ini dalam sebuah fragmen dan itu macet jika saya mencoba kembali ke fragmen ini

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

setelah mengumpulkan jawaban di utas ini, saya menyadari bahwa orang tua mRootView masih memiliki mRootView sebagai anak. Jadi, inilah perbaikan saya.

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

semoga ini membantu

pengguna1736525
sumber
2
+1 membantu saya. Terutama benar jika aktivitas Anda tetap ada tetapi pengelola fragmen menambahkan fragmen baru di atasnya. saat kembali ke fragmen pertama, perlu memastikan tampilan root lama dihapus. Terima kasih!
Bundeeteddee
Itu sangat membantu saya. Saya telah menemukan solusi itu selama 3 hari. Jawaban sederhana dan cantik.
Zin Win Htet
Wow! akhirnya itu berhasil untuk saya! solusi gratis. Terima kasih!
avisper
Saya tidak punya alasan mengapa "(ViewGroup) mRootView.getParent ()). RemoveView (mRootView);" bekerja berbeda dengan langsung memanggil "<WhateverIsParentViewGroupName> .removeView (mRootView)" Tapi ini juga berfungsi untuk saya, saya sedang menguji di Android 8.0 dan 9.0. Terima kasih bud ^
Khay
16

Ini juga terjadi saat tampilan yang dikembalikan oleh onCreateView () bukan tampilan yang digelembungkan.

Contoh:

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;

Memperbaiki:

return rootView;

Dari pada:

return textView; // or whatever you returned
Mateus Pires
sumber
Terima kasih! itu membantu saya!
Sudheesh Mohan
5

Saya punya masalah ini dan tidak bisa menyelesaikannya dalam kode Java. Masalahnya ada pada xml saya.

Saya mencoba menambahkan textView ke wadah, tetapi telah membungkus textView di dalam LinearLayout.

Ini adalah file xml asli:

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

Sekarang dengan LinearLayout dihapus:

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

Ini sepertinya tidak banyak bagi saya tetapi berhasil, dan saya tidak mengubah kode Java saya sama sekali. Semuanya ada di xml.

DroidCrafter
sumber
2

Anda menambahkan Viewke dalam layout, tetapi Tampilan sudah ada di yang lain layout. Tampilan tidak boleh di lebih dari satu tempat.

cupu
sumber
saya menambahkan lebih banyak detail ke pertanyaan saya, tolong dapatkah Anda melihatnya?
haythem souissi
1

Solusi ini dapat membantu:

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;
    }
}
Bhavit S. Sengar
sumber
1
Saya pikir rootView akan selalu null karena Anda tidak menginisialisasinya.
Zin Win Htet
rootView selalu nol
Thinsky
1

Aku dipecahkan dengan menetapkan attachToRootdari inflater.inflate()ke false.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_overview, container, false);
    return view;
}
Tuan B.
sumber
0

di file xml Anda, Anda harus mengatur layout_width dan layout_height dari wrap_content ke match_parent. itu sudah diperbaiki untuk saya.

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Evan Ngo
sumber