我已经看过这里的每一个错误,但没有任何修复它。我试图以编程方式将一个片段添加到我的活动中(在其他代码的帮助下)并运行它并得到此错误:
IllegalStateException, the specified child already has a parent, you must call removeView() on the child's parent first.
我有一个活动只是托管一个片段,在FrameLayout
中使用xml
,然后我在该活动中编码FragmentManager
以启动它。我的片段视图的详细信息位于我的片段类onCreateView()
中,ContactsFragment.java
。在这里,我指定了一个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_width="match_parent"
android:layout_height="match_parent"
tools:context="org.azurespot.practiceapp.addressbook.AddressBook" >
<FrameLayout
android:id="@+id/contacts_fragment"
android:layout_width="0dp"
android:layout_height="match_parent" >
</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://stackoverflow.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_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
</ListView>
<TextView
android:id="@id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
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_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/contact_thumbnail"
android:layout_width="50dp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10" >
</TextView>
<TextView
android:id="@+id/contact_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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 ComponentInfo{com.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 more
答案 0 :(得分: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_width="match_parent"
android:background="#FF0000"
android:layout_height="match_parent" >
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
</ListView>
<TextView
android:id="@id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="match_parent"
tools:context="org.azurespot.practiceapp.addressbook.AddressBook" >
<FrameLayout
android:id="@+id/contacts_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>