Android Question The specified child already has a parent

techknight

Well-Known Member
Licensed User
Longtime User
I am attempting to create a dynamically allocated panel situation which gets added into the customlistview, based on the number of connected UI classes.

It works fine if theres only one connected class/panel. The minute there are two or more, I get an IllegalStateException that the specified child already has a parent and a crash

I am probably making a mistake somewhere in the code, but I am declaring an ItemPanel each time so I am not sure why this is occuring.

pnlWidget are the parent panels for the class array, that gets initialized and setup early on during the Activity load. Those are all good.

Here is the code:

B4X:
'Refresh widgets in the list views.
Sub UpdateWidgets
   
    Log("Updatewidgets called")
   
    'Enumerate through all widgets, accumulate the total of connected widgets for a specific scoreboard.
    Dim NumWidgetsNeeded As Int = 0
    Dim IndexMap As Map
   
    'Accumulate the total number of connected scoreboard operators, store each connected parent panel in the hashtable
    IndexMap.Initialize
    For I = 0 To ScoreWidgets.Length-1
        If ScoreWidgets(I).IsInitialized = True Then         'Make sure the particular widget was initialized to begin with before running our tests
            If ScoreWidgets(I).IsConnected = True Then
                IndexMap.Put(NumWidgetsNeeded, I)                'Store the parent panel index location in the given hashtable
                Log(NumWidgetsNeeded & "," & I)
                NumWidgetsNeeded = NumWidgetsNeeded + 1            'Accumulate to the total of connected widgets
            End If
        End If
    Next   
   
    If NumWidgetsNeeded = 0 Then     'There are no active connections
        clvRight.Clear
        clvLeft.clear
        Return
    End If
   
    'Add currently connected scoreboard widgets to the list view
    'Lets determine the maximum number of widgets that can be shown in a listview.
    Dim MaxWidgets As Int = Floor(clvLeft.AsView.Height / pnlWidget(0).Height)        'Maximum number of widgets the view can actually hold   
   
    If MaxWidgets < NumWidgetsNeeded Then     'If the number of widgets needed exceed that of the views capability, we have to span views
        'Make sure both listviews are visible and aligned properly.
        clvLeft.Clear
        clvRight.Clear
       
        clvLeft.AsView.Left = InitialLeftPosition
        clvRight.AsView.Left = InitialRightPosition
       
        clvLeft.AsView.Visible = True
        clvRight.AsView.Visible = True       
       
        'formula for determining spacing:
        'Spacing = (ListView Height - (Widget Height x NumWidgets)) / NumWidgets
        Dim Spacing As Int = (clvLeft.AsView.Height - (pnlWidget(0).Height * MaxWidgets)) / MaxWidgets
        For I = 0 To MaxWidgets-1
            Dim ItemPanel As Panel
            Dim PanelIndex As Int = IndexMap.Get(I)        'Get the reference index from the hashtable
            ItemPanel.Initialize("")
            ItemPanel.SetLayout(0,0,pnlWidget(PanelIndex).Width, (Spacing + pnlWidget(PanelIndex).Height))        'Create a panel and set the height of the panel the same as the Widget, plus the spacing.
            ItemPanel.AddView(pnlWidget(PanelIndex), 0, (Spacing/2), pnlWidget(PanelIndex).Width, pnlWidget(PanelIndex).Height)    'Add the widget in the center of the panel
            clvLeft.Add(ItemPanel, i)        'Add the new itempanel into the listview
        Next           
           
        'Dump the excess off into the 2nd view
        Spacing = (clvRight.AsView.Height - (pnlWidget(0).Height * (NumWidgetsNeeded - MaxWidgets))) / (NumWidgetsNeeded - MaxWidgets)
       
        Dim I2 As Int = 0
       
        For I = MaxWidgets To NumWidgetsNeeded-1
            Dim ItemPanel As Panel
            Dim PanelIndex As Int = IndexMap.Get(I)        'Get the reference index from the hashtable
            ItemPanel.Initialize("")
            ItemPanel.SetLayout(0,0,pnlWidget(PanelIndex).Width, (Spacing + pnlWidget(PanelIndex).Height))            'Create a panel and set the height of the panel the same as the Widget, plus the spacing.
            ItemPanel.AddView(pnlWidget(PanelIndex), 0, (Spacing/2), pnlWidget(PanelIndex).Width, pnlWidget(PanelIndex).Height)    'Add the widget in the center of the panel
           
            clvRight.Add(ItemPanel, I2)
            I2 = I2 + 1
        Next
       
    Else    'Everything should fit in a single listview.
       
        clvRight.Clear
        clvLeft.clear   
       
        'formula for determining spacing:
        'Spacing = (ListView Height - (Widget Height x NumWidgets)) / NumWidgets
        Dim Spacing As Int = (clvLeft.AsView.Height - (pnlWidget(0).Height * NumWidgetsNeeded)) / NumWidgetsNeeded   
       
        If Spacing < 0 Then Spacing = 0
        For I = 0 To NumWidgetsNeeded-1
            Dim PanelIndex As Int = IndexMap.Get(I)        'Get the reference index from the hashtable
            Dim ItemPanel As Panel
            ItemPanel.Initialize("")
            ItemPanel.RemoveAllViews
            ItemPanel.SetLayout(0,0,pnlWidget(PanelIndex).Width, (Spacing + pnlWidget(PanelIndex).Height))        'Create a panel and set the height of the panel the same as the Widget, plus the spacing.
            ItemPanel.AddView(pnlWidget(PanelIndex), 0, (Spacing/2), pnlWidget(PanelIndex).Width, pnlWidget(PanelIndex).Height)    'Add the widget in the center of the panel (THIS IS THE ERROR)
           
            clvLeft.Add(ItemPanel, i)
            'clvLeft.ResizeItem(i,pnlWidget(i).Height + Spacing)           
        Next           
       
    End If   
   
    Log("updatewidgets exited")
   
End Sub

And, here is the error:
B4X:
Updatewidgets called
0,2
updatewidgets exited
Updatewidgets called
0,2
1,5
Error occurred on line: 476 (Main)
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:5034)
    at android.view.ViewGroup.addView(ViewGroup.java:4865)
    at android.view.ViewGroup.addView(ViewGroup.java:4837)
    at anywheresoftware.b4a.objects.PanelWrapper.AddView(PanelWrapper.java:65)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:777)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:354)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
    at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:1082)
    at anywheresoftware.b4a.keywords.Common.CallSubNew2(Common.java:1037)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:262)
    at edge.scoremonitor.scorewidget._connectionmanager_handleconnect(scorewidget.java:385)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:318)
    at anywheresoftware.b4a.debug.Debug.CallSubNew(Debug.java:282)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.keywords.Common.CallSubDebug(Common.java:1050)
    at edge.scoremonitor.connectionmanager._parsedata(connectionmanager.java:446)
    at edge.scoremonitor.connectionmanager._mqtt_messagearrived(connectionmanager.java:387)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
    at anywheresoftware.b4a.BA$2.run(BA.java:387)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6680)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Any thoughts? Thanks
 

techknight

Well-Known Member
Licensed User
Longtime User
I fixed it by adding a RemoveView line in there, but I have a fear that its probably gobbling up memory leaving things dangling
1705350591112.png
 
Upvote 0

Spavlyuk

Active Member
Licensed User
You're probably trying to add the same pnlWidget to two different panels, which is why you're getting that error message.
Make sure the index of your loops is not being reused.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
You're probably trying to add the same pnlWidget to two different panels, which is why you're getting that error message.
Make sure the index of your loops is not being reused.

I dont think I am, the code above is the only code that deals with these panels. I guess clearing the customlistview isnt actually clearing the panels away, and since the subroutine returns and comes back, I lose the reference pointers to the panels from before.

Thats the only thing I can think of what is happening here, which is why removeview somehow fixes it.
 
Upvote 0
Top