Android Question Why can't a code module hold a reference to class from activity?

Sandman

Expert
Licensed User
Longtime User
I'm making a somewhat large library, and in this library I have a code module to hold references to some classes that are common for me to use in the library.

The classes are always initialized within an activity context, and from that activity they are set in the code module. Some of the classes reference B4XViews, which is a variable that needs an activity context.

So, again: The code module only holds references to classes that were created in, and set from, an activity. (And I'm using B4XPages so it's actually the activity Main, and I do all this from B4XMainPage.)

But when I do this, I get this error:
B4X:
Cannot access activity object from sub Process_Globals.


I can understand that it wouldn't be possible to create and hold classes that require activity context from within a code module. But I wouldn't expect a problem when I create and set the class from the outside, from an activity. And then the code module only holds a reference.

Part of me feels like I might have found some edge-case bug in B4A, and part of me feels like there is some extra constraint that I don't understand or know about.

Anyone have an idea about this?



I have attached a super small demo project to show the situation. Here's all the relevant code in the project:


B4XMainPage:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    
    Public MyClassModule1 As MyClassModule ' This is where the class is defined and inited
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    
    MyClassModule1.Initialize
    MyClassModule1.Beep
    MyCodeModule.ReferenceHolder = MyClassModule1 ' Setting a reference in the code module
End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Private Sub Button1_Click
    xui.MsgboxAsync("Hello world!", "B4X")
End Sub

MyClassModule:
Sub Class_Globals
    Private thing As B4XView ' This requires an activity context
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
End Sub

Public Sub Beep
    Log("Boop")
End Sub

MyCodeModule:
'Code module
'Subs in this code module will be accessible from all modules.
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

    Dim ReferenceHolder As MyClassModule ' This produces the error
End Sub
 

Attachments

  • Project.zip
    14.7 KB · Views: 127

agraham

Expert
Licensed User
Longtime User
It's a deliberate memory management design feature of B4A to avoid references to instances of controls etc. that might be owned by an Activity. If you could hold a reference to, say a Button, in a process global then when the Activity is available for garbage collection, there being no outstanding references to it, the garbage collector will not be able to remove it from memory because you are holding a reference to a Button it owns. In turn all the other object instances that the Activity holds will themselves not be able to be garbage collected because the activity is holding references to them and so on. So your one tiny reference can block a large amount of memory from being freed.

This can be a problem if you are coding in Java and don't know that the problem exists so Erel chose to enforce it in B4A.
 
Upvote 1

Sandman

Expert
Licensed User
Longtime User
Thanks for the explanation, it does make sense.

(Not that it matters a whole lot, but I think that in my case none of the classes would be up for garbage collection anyway, so it would be ok to hold a reference to them.)
 
Upvote 0
Top