Android Question Why can't I LoadLayout in class?

RB Smissaert

Well-Known Member
Licensed User
Longtime User
I have a progressbar class which is running from a B4XPage.
The progressbar class has a layout, which needs to be loaded.
When I load the layout first from the B4XPage and then make calls to the progressbar class there is no problem and all runs fine.
As this progress bar in various places in the project I thought I could do the loading of the layout in the progressbar class instead
and save some lines of code.
When I do this however I run into this error:

B4X:
b4xprogressbar$ResumableSub_Load_Layoutresume (java line: 648)
java.lang.RuntimeException: java.lang.NullPointerException: Attempt to read from field 'java.lang.Object anywheresoftware.b4a.BA.eventsTarget' on a null object reference in method 'anywheresoftware.b4a.keywords.LayoutBuilder$LayoutValuesAndMap anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(java.lang.String, anywheresoftware.b4a.BA, boolean, android.view.ViewGroup, java.util.LinkedHashMap)'
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:155)
    at anywheresoftware.b4a.objects.PanelWrapper.LoadLayout(PanelWrapper.java:134)
    at anywheresoftware.b4a.objects.B4XViewWrapper.LoadLayout(B4XViewWrapper.java:329)
    at b4a.exampleljjll.b4xprogressbar$ResumableSub_Load_Layout.resume(b4xprogressbar.java:648)
    at b4a.exampleljjll.b4xprogressbar._load_layout(b4xprogressbar.java:625)
    at b4a.exampleljjll.b4xprogressbar$ResumableSub_Show.resume(b4xprogressbar.java:840)
    at b4a.exampleljjll.b4xprogressbar._show(b4xprogressbar.java:800)
    at b4a.exampleljjll.p_map$ResumableSub_LogMissingTilesInPolygon.resume(p_map.java:7526)
    at b4a.exampleljjll.p_map._logmissingtilesinpolygon(p_map.java:6880)
    at b4a.exampleljjll.p_map$ResumableSub_ShowAreaTiles.resume(p_map.java:13288)
    at b4a.exampleljjll.p_map._showareatiles(p_map.java:13223)
    at b4a.exampleljjll.p_map$ResumableSub_PatientsInAreaDialog.resume(p_map.java:8523)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:275)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.keywords.Common$15.run(Common.java:1804)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:9063)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: java.lang.NullPointerException: Attempt to read from field 'java.lang.Object anywheresoftware.b4a.BA.eventsTarget' on a null object reference in method 'anywheresoftware.b4a.keywords.LayoutBuilder$LayoutValuesAndMap anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(java.lang.String, anywheresoftware.b4a.BA, boolean, android.view.ViewGroup, java.util.LinkedHashMap)'
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:133)
    ... 23 more
Starter, LogError, strErrorMsg: java.lang.RuntimeException: java.lang.NullPointerException: Attempt to read from field 'java.lang.Object anywheresoftware.b4a.BA.eventsTarget' on a null object reference in method 'anywheresoftware.b4a.keywords.LayoutBuilder$LayoutValuesAndMap anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(java.lang.String, anywheresoftware.b4a.BA, boolean, android.view.ViewGroup, java.util.LinkedHashMap)'

This is the code in the B4XPage:

B4X:
        'Root.LoadLayout("ProgressBar")  'With this (and not loading the layout in clsProgressBar) it runs all fine
        Dim rs As ResumableSub = clsProgressBar.Show(Root, iMaxTilesToCheck, False, 1, "Find missing tiles", "", "/", " done")
        Wait For (rs) Complete (bDone As Boolean)

And this the relevant code in the progressbar class:

B4X:
Sub Load_Layout(vParent As B4XView) As ResumableSub
    
'    Log("vParent.Tag: " & vParent.Tag)
    
    vParent.LoadLayout("ProgressBar")
    
    Return True
    
End Sub

Public Sub Show(Parent As B4XView, _
                iMax As Int, _
                bAnimateValues As Boolean, _
                iProgressPosition As Int, _
                strTitle As String, _
                strDone As String, _
                strValuesSeparator As String, _
                strToDo As String) As ResumableSub
                
'    Parent.LoadLayout("ProgressBar")
                
'    Log("Show")
'    Log("Parent.Tag: " & Parent.Tag)

    Dim rs As ResumableSub = Load_Layout(Parent)
    Wait For (rs) Complete (bDone As Boolean)

I made ResumableSubs in case there was a timing issue, but to no avail.

Thanks for any insight in this problem.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
Longtime User
I have a progressbar class which is running from a B4XPage.
The progressbar class has a layout, which needs to be loaded.
When I load the layout first from the B4XPage and then make calls to the progressbar class there is no problem and all runs fine.
As this progress bar in various places in the project I thought I could do the loading of the layout in the progressbar class instead
and save some lines of code.
When I do this however I run into this error:

B4X:
b4xprogressbar$ResumableSub_Load_Layoutresume (java line: 648)
java.lang.RuntimeException: java.lang.NullPointerException: Attempt to read from field 'java.lang.Object anywheresoftware.b4a.BA.eventsTarget' on a null object reference in method 'anywheresoftware.b4a.keywords.LayoutBuilder$LayoutValuesAndMap anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(java.lang.String, anywheresoftware.b4a.BA, boolean, android.view.ViewGroup, java.util.LinkedHashMap)'
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:155)
    at anywheresoftware.b4a.objects.PanelWrapper.LoadLayout(PanelWrapper.java:134)
    at anywheresoftware.b4a.objects.B4XViewWrapper.LoadLayout(B4XViewWrapper.java:329)
    at b4a.exampleljjll.b4xprogressbar$ResumableSub_Load_Layout.resume(b4xprogressbar.java:648)
    at b4a.exampleljjll.b4xprogressbar._load_layout(b4xprogressbar.java:625)
    at b4a.exampleljjll.b4xprogressbar$ResumableSub_Show.resume(b4xprogressbar.java:840)
    at b4a.exampleljjll.b4xprogressbar._show(b4xprogressbar.java:800)
    at b4a.exampleljjll.p_map$ResumableSub_LogMissingTilesInPolygon.resume(p_map.java:7526)
    at b4a.exampleljjll.p_map._logmissingtilesinpolygon(p_map.java:6880)
    at b4a.exampleljjll.p_map$ResumableSub_ShowAreaTiles.resume(p_map.java:13288)
    at b4a.exampleljjll.p_map._showareatiles(p_map.java:13223)
    at b4a.exampleljjll.p_map$ResumableSub_PatientsInAreaDialog.resume(p_map.java:8523)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:275)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.keywords.Common$15.run(Common.java:1804)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:9063)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: java.lang.NullPointerException: Attempt to read from field 'java.lang.Object anywheresoftware.b4a.BA.eventsTarget' on a null object reference in method 'anywheresoftware.b4a.keywords.LayoutBuilder$LayoutValuesAndMap anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(java.lang.String, anywheresoftware.b4a.BA, boolean, android.view.ViewGroup, java.util.LinkedHashMap)'
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:133)
    ... 23 more
Starter, LogError, strErrorMsg: java.lang.RuntimeException: java.lang.NullPointerException: Attempt to read from field 'java.lang.Object anywheresoftware.b4a.BA.eventsTarget' on a null object reference in method 'anywheresoftware.b4a.keywords.LayoutBuilder$LayoutValuesAndMap anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(java.lang.String, anywheresoftware.b4a.BA, boolean, android.view.ViewGroup, java.util.LinkedHashMap)'

This is the code in the B4XPage:

B4X:
        'Root.LoadLayout("ProgressBar")  'With this (and not loading the layout in clsProgressBar) it runs all fine
        Dim rs As ResumableSub = clsProgressBar.Show(Root, iMaxTilesToCheck, False, 1, "Find missing tiles", "", "/", " done")
        Wait For (rs) Complete (bDone As Boolean)

And this the relevant code in the progressbar class:

B4X:
Sub Load_Layout(vParent As B4XView) As ResumableSub
   
'    Log("vParent.Tag: " & vParent.Tag)
   
    vParent.LoadLayout("ProgressBar")
   
    Return True
   
End Sub

Public Sub Show(Parent As B4XView, _
                iMax As Int, _
                bAnimateValues As Boolean, _
                iProgressPosition As Int, _
                strTitle As String, _
                strDone As String, _
                strValuesSeparator As String, _
                strToDo As String) As ResumableSub
               
'    Parent.LoadLayout("ProgressBar")
               
'    Log("Show")
'    Log("Parent.Tag: " & Parent.Tag)

    Dim rs As ResumableSub = Load_Layout(Parent)
    Wait For (rs) Complete (bDone As Boolean)

I made ResumableSubs in case there was a timing issue, but to no avail.

Thanks for any insight in this problem.

RBS
Now for some reason I can't run this anymore, even with loading the layout in the B4XPage.
The error I get is this:

B4X:
DesignerCreateView
Base_Resize
DrawValue
Show 1
Parent.Tag: 22
b4xprogressbar_show (java line: 821)
java.lang.RuntimeException: Object should first be initialized (Panel).
Did you forget to call Activity.LoadLayout?
    at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
    at anywheresoftware.b4a.objects.ViewWrapper.setVisible(ViewWrapper.java:271)
    at b4a.exampleljjll.b4xprogressbar._show(b4xprogressbar.java:821)
    at b4a.exampleljjll.p_map$ResumableSub_LogMissingTilesInPolygon.resume(p_map.java:7571)
    at b4a.exampleljjll.p_map._logmissingtilesinpolygon(p_map.java:6926)
    at b4a.exampleljjll.p_map$ResumableSub_ShowAreaTiles.resume(p_map.java:13324)
    at b4a.exampleljjll.p_map._showareatiles(p_map.java:13259)
    at b4a.exampleljjll.p_map$ResumableSub_PatientsInAreaDialog.resume(p_map.java:8559)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:275)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.keywords.Common$15.run(Common.java:1804)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:9063)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Starter, LogError, strErrorMsg: java.lang.RuntimeException: Object should first be initialized (Panel).
Did you forget to call Activity.LoadLayout?

No idea why this now causes an error and before was running fine.
The above panel that was not initialized is a panel in the layout holding the custom view B4XProgressBar1 and also 2 normal labels.

Maybe all the code that refers to the views on that panel (and that panel itself) should be in the B4XPage and loading the layout should then
be done in the B4XPage. Problem with that though is that this progressbar is used in several B4XPages, so it would lead to code duplication.
All in all a bit of a mess, but I will get this sorted.

RBS
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
When you load a layout in class 'X', the context for all the layout related events will be that class.
As well, the object tree of views with root node "Root" will be in future instances of that class.

Re-using the loaded views in another class is not an option.
That being said, all objects (including those views) can be accessed from anywhere in the project if...
1. You make them public.
Or...
2. Have a Public method that accesses the private object in the instance of that "X'.

But, for example, if make a view say a different color, you won't see it until the instance of that class that holds the view is shown.

Of course, you can simply load the same layout in multiple classes. Just put the preparations of views in a Sub and call it after the LoadLayout.
Then you won't need to replicate the bulky part of the code.
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
When you load a layout in class 'X', the context for all the layout related events will be that class.
As well, the object tree of views with root node "Root" will be in future instances of that class.

Re-using the loaded views in another class is not an option.
That being said, all objects (including those views) can be accessed from anywhere in the project if...
1. You make them public.
Or...
2. Have a Public method that accesses the private object in the instance of that "X'.

But, for example, if make a view say a different color, you won't see it until the instance of that class that holds the view is shown.

Of course, you can simply load the same layout in multiple classes. Just put the preparations of views in a Sub and call it after the LoadLayout.
Then you won't need to replicate the bulky part of the code.
> Of course, you can simply load the same layout in multiple classes. Just put the preparations of views in a Sub and call it after the LoadLayout.

That is what I had done before and it worked all fine, and still no idea why exactly that now gives errors.
I think loading the layout in the B4XPages is the simplest solution.
Will post some more code later.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
When you load a layout in class 'X', the context for all the layout related events will be that class.
As well, the object tree of views with root node "Root" will be in future instances of that class.

Re-using the loaded views in another class is not an option.
That being said, all objects (including those views) can be accessed from anywhere in the project if...
1. You make them public.
Or...
2. Have a Public method that accesses the private object in the instance of that "X'.

But, for example, if make a view say a different color, you won't see it until the instance of that class that holds the view is shown.

Of course, you can simply load the same layout in multiple classes. Just put the preparations of views in a Sub and call it after the LoadLayout.
Then you won't need to replicate the bulky part of the code.
I am just thinking the simplest way to solve all this is avoid having the custom view.
This is for a simple progressbar and I am sure I can make that without a custom view.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Now for some reason I can't run this anymore, even with loading the layout in the B4XPage.
The error I get is this:

B4X:
DesignerCreateView
Base_Resize
DrawValue
Show 1
Parent.Tag: 22
b4xprogressbar_show (java line: 821)
java.lang.RuntimeException: Object should first be initialized (Panel).
Did you forget to call Activity.LoadLayout?
    at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
    at anywheresoftware.b4a.objects.ViewWrapper.setVisible(ViewWrapper.java:271)
    at b4a.exampleljjll.b4xprogressbar._show(b4xprogressbar.java:821)
    at b4a.exampleljjll.p_map$ResumableSub_LogMissingTilesInPolygon.resume(p_map.java:7571)
    at b4a.exampleljjll.p_map._logmissingtilesinpolygon(p_map.java:6926)
    at b4a.exampleljjll.p_map$ResumableSub_ShowAreaTiles.resume(p_map.java:13324)
    at b4a.exampleljjll.p_map._showareatiles(p_map.java:13259)
    at b4a.exampleljjll.p_map$ResumableSub_PatientsInAreaDialog.resume(p_map.java:8559)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:275)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.keywords.Common$15.run(Common.java:1804)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:9063)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Starter, LogError, strErrorMsg: java.lang.RuntimeException: Object should first be initialized (Panel).
Did you forget to call Activity.LoadLayout?

No idea why this now causes an error and before was running fine.
The above panel that was not initialized is a panel in the layout holding the custom view B4XProgressBar1 and also 2 normal labels.

Maybe all the code that refers to the views on that panel (and that panel itself) should be in the B4XPage and loading the layout should then
be done in the B4XPage. Problem with that though is that this progressbar is used in several B4XPages, so it would lead to code duplication.
All in all a bit of a mess, but I will get this sorted.

RBS
Have solved this now, with the layout loaded from the B4XPage (as I had it before).
I think the errors I experienced with that was caused by Initializing the progressbar class in the B4XPage in the one particular B4XPage,
that is the page I was testing this with.

RBS
 
Upvote 0
Top