IllegalStateException,指定的孩子已经有一个父母 - ListFragment
Posted
技术标签:
【中文标题】IllegalStateException,指定的孩子已经有一个父母 - ListFragment【英文标题】:IllegalStateException, the specified child already has a parent - ListFragment 【发布时间】:2015-02-24 18:36:41 【问题描述】:我已经查看了这里的所有此类错误,但没有任何解决方法。我正在尝试以编程方式向我的活动添加一个片段(在其他代码的帮助下),我运行它并收到此错误:
IllegalStateException, the specified child already has a parent, you must call removeView() on the child's parent first.
我有一个活动只是托管一个片段,在其xml
中使用FrameLayout
,然后我在该活动中编码FragmentManager
以启动它。我的片段视图的详细信息在我的片段类ContactsFragment.java
的onCreateView()
中。在这里,我分配了一个ListView
作为我希望在名为AddressBook.java
的活动中查看的片段。
感谢您的帮助,如果您能发现我的代码中的任何错误。 Activity、Fragment、xmls和logcat如下。
编辑:当我取出 FragmentManager 代码时,错误消失了,但随后我得到一个空白的白色活动。这是否有助于任何人更多地了解错误的性质?谢谢。
代码注释掉:
// Begin the transaction
FragmentTransaction ft = getFragmentManager().beginTransaction();
// Replace the container with the new fragment
ft.add(R.id.contacts_fragment, new ContactsFragment());
// Execute the changes specified
ft.commit();
AddressBook.java
package org.azurespot.practiceapp.addressbook;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import com.example.practiceapp.R;
public class AddressBook extends Activity
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_address_book);
// Begin the transaction
FragmentTransaction ft = getFragmentManager().beginTransaction();
// Replace the container with the new fragment
ft.replace(R.id.contacts_fragment, new ContactsFragment());
// or ft.add(R.id.your_placeholder, new FooFragment());
// Execute the changes specified
ft.commit();
activity_address_book.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context="org.azurespot.practiceapp.addressbook.AddressBook" >
<FrameLayout
android:id="@+id/contacts_fragment"
android:layout_
android:layout_ >
</FrameLayout>
</LinearLayout>
ContactsFragment.java
package org.azurespot.practiceapp.addressbook;
import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import com.example.practiceapp.R;
/*
* Partially from http://***.com/questions/18199359/how-to-display-contacts-in-a-listview-in-android-for-android-api-11
*/
public class ContactsFragment extends ListFragment implements
LoaderCallbacks<Cursor>
private CursorAdapter listAdapter;
public Cursor cursor;
private android.content.Context context;
public View view;
public static Uri uri;
public static ListView listView;
public static final String[] FROM = new String[]
ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER ;
private static final int[] TO = R.id.contact_thumbnail,
R.id.contact_name, R.id.contact_number ;
// columns requested from the database
private static final String[] PROJECTION = new String[]
ContactsContract.Contacts._ID,
ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
;
// this goes in the CursorLoader parameter list, it filters
// out only those contacts who have a phone number
private static final String FILTER =
ContactsContract.Contacts.HAS_PHONE_NUMBER + " LIKE ?";
private static final int URL_LOADER = 0;
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,Bundle bundle)
if(listView != null)
return listView;
// since using ListFragment, you must inflate your view this way
View rootView = inflater.inflate(R.layout.fragment_list_view,
container, false);
listView = (ListView) rootView
.findViewById(android.R.id.list);
// create a new SimpleCursorAdapter adapter
context = getActivity();
Cursor c = null; // there is no cursor yet
int flags = 0; // no auto-re-query! (My loader re-queries.)
// put List UI row in adapter, create empty adapter
listAdapter = new SimpleCursorAdapter(context,
R.layout.fragment_list_item, c, FROM, TO, flags);
// Initializes the CursorLoader. The URL_LOADER value is
// eventually passed to onCreateLoader().
getLoaderManager().initLoader(URL_LOADER, null, this);
// ListFragment then sets the adapter
ContactsFragment listFrag = new ContactsFragment();
listFrag.setListAdapter(listAdapter);
return listView;
// end onCreateView
// Empty public constructor, required by the system
public ContactsFragment()
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
/*
* The 3 methods below are standard for the LoaderCallbacks<Cursor> interface.
* Here, CursorLoader does a query in the background.
*/
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args)
// load from the "Contacts table"
Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
// the query
return new CursorLoader(getActivity(),
contentUri,
PROJECTION,
FILTER,
null,
ContactsContract.Contacts.DISPLAY_NAME + " ASC");
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
// Once cursor is loaded, give it to adapter
listAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed())
setListShown(true);
else
setListShownNoAnimation(true);
@Override
public void onLoaderReset(Loader<Cursor> loader)
// Delete the reference to the existing Cursor,
// so it can recycle it
listAdapter.swapCursor(null);
fragment_list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_ >
<ListView
android:id="@android:id/list"
android:layout_
android:layout_
android:layout_weight="1" >
</ListView>
<TextView
android:id="@id/android:empty"
android:layout_
android:layout_
android:background="#FF0000"
android:text="No data"/>
</LinearLayout>
fragment_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_ >
<ImageView
android:id="@+id/contact_thumbnail"
android:layout_
android:layout_ />
<TextView
android:id="@+id/contact_name"
android:layout_
android:layout_
android:layout_weight="1"
android:ems="10" >
</TextView>
<TextView
android:id="@+id/contact_number"
android:layout_
android:layout_
android:layout_weight="1"
android:ems="10" >
</TextView>
</LinearLayout>
Logcat
12-27 22:37:17.145: I/PersonaManager(12130): getPersonaService() name persona_policy
12-27 22:37:17.165: D/skia(12130): GFXPNG PNG bitmap created width:48 height:48 bitmap id is 270
12-27 22:37:17.175: E/MoreInfoHPW_ViewGroup(12130): Parent view is not a TextView
12-27 22:37:17.185: D/skia(12130): GFXPNG PNG bitmap created width:72 height:72 bitmap id is 271
12-27 22:37:17.185: D/skia(12130): GFXPNG PNG bitmap created width:144 height:144 bitmap id is 272
12-27 22:37:17.205: D/skia(12130): GFXPNG PNG bitmap created width:144 height:144 bitmap id is 273
12-27 22:37:17.295: I/Adreno-EGL(12130): <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: ()
12-27 22:37:17.295: I/Adreno-EGL(12130): OpenGL ES Shader Compiler Version: E031.24.00.08+13
12-27 22:37:17.295: I/Adreno-EGL(12130): Build Date: 03/20/14 Thu
12-27 22:37:17.295: I/Adreno-EGL(12130): Local Branch: 0320_AU200_patches
12-27 22:37:17.295: I/Adreno-EGL(12130): Remote Branch:
12-27 22:37:17.295: I/Adreno-EGL(12130): Local Patches:
12-27 22:37:17.295: I/Adreno-EGL(12130): Reconstruct Branch:
12-27 22:37:17.325: D/OpenGLRenderer(12130): Enabling debug mode 0
12-27 22:37:18.705: I/PersonaManager(12130): getPersonaService() name persona_policy
12-27 22:37:18.715: E/MoreInfoHPW_ViewGroup(12130): Parent view is not a TextView
12-27 22:37:18.735: D/skia(12130): GFXPNG PNG bitmap created width:12 height:12 bitmap id is 274
12-27 22:37:18.735: D/AbsListView(12130): Get MotionRecognitionManager
12-27 22:37:18.745: D/AndroidRuntime(12130): Shutting down VM
12-27 22:37:18.745: W/dalvikvm(12130): threadid=1: thread exiting with uncaught exception (group=0x41737da0)
12-27 22:37:18.745: E/AndroidRuntime(12130): FATAL EXCEPTION: main
12-27 22:37:18.745: E/AndroidRuntime(12130): Process: com.example.practiceapp, PID: 12130
12-27 22:37:18.745: E/AndroidRuntime(12130): java.lang.RuntimeException: Unable to start activity ComponentInfocom.example.practiceapp/org.azurespot.practiceapp.addressbook.AddressBook: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2395)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2453)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.ActivityThread.access$900(ActivityThread.java:173)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.os.Handler.dispatchMessage(Handler.java:102)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.os.Looper.loop(Looper.java:136)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.ActivityThread.main(ActivityThread.java:5579)
12-27 22:37:18.745: E/AndroidRuntime(12130): at java.lang.reflect.Method.invokeNative(Native Method)
12-27 22:37:18.745: E/AndroidRuntime(12130): at java.lang.reflect.Method.invoke(Method.java:515)
12-27 22:37:18.745: E/AndroidRuntime(12130): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
12-27 22:37:18.745: E/AndroidRuntime(12130): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
12-27 22:37:18.745: E/AndroidRuntime(12130): at dalvik.system.NativeStart.main(Native Method)
12-27 22:37:18.745: E/AndroidRuntime(12130): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.view.ViewGroup.addViewInner(ViewGroup.java:3771)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.view.ViewGroup.addView(ViewGroup.java:3624)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.view.ViewGroup.addView(ViewGroup.java:3569)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.view.ViewGroup.addView(ViewGroup.java:3545)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:901)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.BackStackRecord.run(BackStackRecord.java:684)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1453)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.Activity.performStart(Activity.java:5460)
12-27 22:37:18.745: E/AndroidRuntime(12130): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2368)
12-27
22:37:18.745: E/AndroidRuntime(12130): ... 11 更多
【问题讨论】:
【参考方案1】:在“ContactsFragment.java”类中,您不会返回膨胀的视图。而是返回列表视图。尝试更改代码如下
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,Bundle bundle)
// since using ListFragment, you must inflate your view this way
View rootView = inflater.inflate(R.layout.fragment_list_view,
container, false);
return rootView;
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
listView = (ListView)getListView();
// create a new SimpleCursorAdapter adapter
context = getActivity();
Cursor c = null; // there is no cursor yet
int flags = 0; // no auto-re-query! (My loader re-queries.)
// put List UI row in adapter, create empty adapter
listAdapter = new SimpleCursorAdapter(context,
R.layout.fragment_list_item, c, FROM, TO, flags);
// Initializes the CursorLoader. The URL_LOADER value is
// eventually passed to onCreateLoader().
getLoaderManager().initLoader(URL_LOADER, null, this);
setListAdapter(listAdapter);
使用相同的replace()方法是Activity
// Begin the transaction
FragmentTransaction ft = getFragmentManager().beginTransaction();
// Replace the container with the new fragment
ft.replace(R.id.contacts_fragment, new ContactsFragment());
// or ft.add(R.id.your_placeholder, new FooFragment());
// Execute the changes specified
ft.commit();
fragment_list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:background="#FF0000"
android:layout_ >
<ListView
android:id="@android:id/list"
android:layout_
android:layout_
android:layout_weight="1" >
</ListView>
<TextView
android:id="@id/android:empty"
android:layout_
android:layout_
android:background="#FF0000"
android:text="No data"/>
</LinearLayout>
activity_address_book.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context="org.azurespot.practiceapp.addressbook.AddressBook" >
<FrameLayout
android:id="@+id/contacts_fragment"
android:layout_
android:layout_ >
</FrameLayout>
</LinearLayout>
【讨论】:
感谢 droidkid,但我需要自定义布局,因为我想从列表中提取照片缩略图、姓名和电话号码。listView
与rootView
基本相同,因为它被分配给rootView.findViewById(android.R.id.list)
方法。但我确实检查过,用rootView
替换它,我仍然得到一个白页。在 ListFragment 文档中,我得到了 onCreateView()
的说明,除非其中有其他问题。
我做的一件事就是将它添加到我的AddressBook
活动中:FragmentManager fm = getFragmentManager(); if (fm.findFragmentById(R.id.contacts_fragment) == null)fm.beginTransaction().add(R.id.contacts_fragment, new ContactsFragment());
并且错误消失了,但我的列表仍然是空白的,这告诉我 ListView
不是 @987654333 @。我不知道为什么它不是null
,但仍然没有显示任何内容。 :(
好的,很高兴它成功了。您的 prblm 在 onCreateView() 方法中,在那里您创建了另一个 ContactsFragment 实例并将适配器值设置为该方法。这也是在附加片段布局之前完成的。如果您有解决方案,请接受答案
您的旧 FragmentTranscation 代码是正确的。检查
嘿,你是对的,我这样做的顺序肯定与我想象的不同。嗯,非常感谢。你的回答真的是救命稻草。 :)以上是关于IllegalStateException,指定的孩子已经有一个父母 - ListFragment的主要内容,如果未能解决你的问题,请参考以下文章
Recyclerview 中的对话框 - IllegalStateException:指定的孩子已经有一个父母
MvcTest出错java.lang.IllegalStateException:Failed to load ApplicationContext
访问tomcat出现HTTP Status 500 - java.lang.IllegalStateException: No output folder
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
java.lang.IllegalStateException: Method get not annotated with HTTP method type (ex. GET, POST);(代码片