2012-02-06 114 views
9

我知道有幾十個問題會問這個錯誤,但是沒有一個提出的解決方案似乎適用於我的問題,至少我知道。Android - 指定的孩子已經有父母。你必須先調用孩子父母的removeView()

這裏是我的日誌:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 
    at android.view.ViewGroup.addViewInner(ViewGroup.java:1976) 
    at android.view.ViewGroup.addView(ViewGroup.java:1871) 
    at android.view.ViewGroup.addView(ViewGroup.java:1851) 
    at com.android.internal.app.AlertController.setupView(AlertController.java:365) 
    at com.android.internal.app.AlertController.installContent(AlertController.java:206) 
    at android.app.AlertDialog.onCreate(AlertDialog.java:251) 
    at android.app.Dialog.dispatchOnCreate(Dialog.java:307) 
    at android.app.Dialog.show(Dialog.java:225) 
    at com.company.MyApp.MyActivity$7.onItemClick(MyActivity.java:240) 
    at android.widget.AdapterView.performItemClick(AdapterView.java:284) 
    at android.widget.ListView.performItemClick(ListView.java:3513) 
    at android.widget.AbsListView$PerformClick.run(AbsListView.java:1812) 
    at android.os.Handler.handleCallback(Handler.java:587) 
    at android.os.Handler.dispatchMessage(Handler.java:92) 
    at android.os.Looper.loop(Looper.java:130) 
    at android.app.ActivityThread.main(ActivityThread.java:3683) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:507) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
    at dalvik.system.NativeStart.main(Native Method) 

這裏是MyActivity.java的onCreate()。你可以看到一個Dialog Builder被顯示並給出了一些值。無論myDialogLayoutmyDialogBuilder是私有類成員

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    // ... a bunch of init code... 

    // Create a dialog builder 
    myDialogLayout = getLayoutInflater().inflate(R.layout.leaving, null); 
    myDialogBuilder = new AlertDialog.Builder(this) 
     .setTitle("My Title") 
     .setView(myDialogLayout) 
     .setNegativeButton("Cancel", new DialogInterface.OnClickListener() 
     { 
      public void onClick(DialogInterface dialog, int which) {} 
     }); 

    // ... more code ... 
} 

後來,當某個按鈕被點擊我的活動中,myDialogBuilder定製了一下,然後創建一個對話框並顯示。 myDialog是私有類變量/成員:

// Builder customized a bit 
myDialogBuilder 
    .setMessage("custom message here"); 

// Dialog created from Builder 
myDialog = myDialogBuilder.create(); 

// Dialog shown 
myDialog.show(); // <---- MyActivity.java Line: 240 

所以,在我的問題,當我點擊我的按鈕,創建成功的對話框。但是當我按下對話框上的取消並再次按下按鈕後,我看到日誌中顯示的錯誤。出於某種原因,該活動不希望我重用我的myDialog對話框。它是一個班級成員,因此可以從onClick處理程序訪問它。而且每次單擊該按鈕時,myDialog都是一個新的對話框,因爲它每次都是從頭開始創建的myDialogBuilder.create()

任何人都知道問題是什麼?我也嘗試在按下「取消」按鈕時添加myDialog.dismiss(),但這沒有什麼區別。

此外,您可以在我的myDialogBuilder中看到自定義XML佈局用於對話框的視圖。根據錯誤消息,它聽起來像是希望我使用removeView()以刪除在對話框中使用的視圖。但myDialogBuilder.removeView()不是一個有效的方法。

回答

17

myDialogLayout一個類的成員變量?如果是這樣,那麼從第一次顯示對話框時就已經有了一個父對象,然後創建第二個對話框,該對話框也試圖成爲myDialogLayout的父對象。嘗試在每次打開對話框時創建myDialogLayout的新實例。

+2

這是關鍵。我將'myDialogLayout'從一個類成員變量中移除,並將其放在'onClick'處理程序方法的本地。那樣的話,這是一種每次都會膨脹的新佈局。謝謝! – 2012-02-06 22:04:18

3

這是爲什麼建議使用onCreateDialog()onPrepareDialog()方法的一個主要例子。

如果每次按下按鈕時都要實例化myDialog,則會嘗試將先前創建的對話框對象(舊父對象)的視圖附加到新對話框。

已經實例化,顯示和排除的對話只需要再次顯示,而不是完全重新創建。

假設myDialog是一個類成員,請嘗試檢查myDialog是否爲null。如果不爲null,則再次顯示而不是完全實例化它。

編輯 - 下面是我的意思,使用onPrepareDialog()和onCreateDialog()的例子。在Create創建對話框,並且每次顯示時,都會對其進行準備,並通過使用findViewById並清除文本來獲取EditText引用。我們在這裏假設DIALOG_TEST是一個整數常量,在layout/dialog_test.xml中有一個EditText視圖,它帶有id edittext。

@Override 
protected void onPrepareDialog(int id, Dialog dialog) { 

    switch(id){ 

    case DIALOG_TEST: 

     EditText mEditText = (EditText) dialog.findViewById(R.id.edittext); 
     mEditText.setText(""); 
     break; 
    } 

} 

@Override 
protected Dialog onCreateDialog(int id) { 

    AlertDialog.Builder builder = new AlertDialog.Builder(this); 

    switch(id){ 

    case DIALOG_TEST: 

     LinearLayout layout = (LinearLayout) ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.dialog_test, null); 

     builder.setTitle("Enter Something").setView(layout); 
     return builder.create(); 
    } 
} 
+0

對話需要被創建,因爲它的消息(和其他方面)每次都不同。 – 2012-02-06 22:00:59

+0

對話框有一個findViewById方法。您應該使用它來獲取對視圖的引用,然後對其進行更新。 – Maximus 2012-02-06 22:05:45

+0

是的,我意識到這一點。我也在每次改變正面按鈕的'onClick'行爲。我在上面的原文中沒有提到這個,所以我可以簡化這個例子。 – 2012-02-06 22:45:16

相關問題