Android Question Saving space in Sub Globals

BanditMrP

Member
Licensed User
Hi all,

I have a large Activity, which is using tabbed layout to allow an engineer on-site to generate reports when there's no wifi, mobile signal etc., using SQLite.

Everything works fine, however, there's 8 type of report, and they want to be able to create 2 of them at a time.

I recently hit an issue where Sub Globals created a Java Compile error because it was too large.

Reading up on this, there's a limit of 65535 bytes (I think) for the Globals definition.

So, taking into account the following code:
Sub Globals:
Private QFH_Job_Number As String
Private QFH_Contact As String
Private QFH_Department As String
Private QFH_Location As String
Private QFH_Telephone As String
Private QFH_Fax As String
Private QFH_Email As String
Private QFH_Type As String
Private QFH_Serial_No As String
Private QFH_Service_No As String

Would I save any space in the final compiled code by doing the same thing this way:

Sub Globals:
Private QFH_Job_Number, QFH_Contact, QFH_Department, QFH_Location, QFH_Telephone, QFH_Fax, QFH_Email, QFH_Type As String, QFH_Serial_No, QFH_Service_No As String

It achieves the same thing, but does it save space against the 65535 byte limit?

Thanks in advance for looking.
Ian
 

emexes

Expert
Licensed User
Longtime User
From memory, it's not just the Globals Sub limited to 64k, it's any Sub.

But it's a pretty big limit to be running into with simple variables.

I vaguely remember a situation with OBDII where we split the big Sub into a few smaller Subs.

Are there any groups of variables that can be combined into one? Like, if you had ten addresses, each with the same fields?

Can you post the entire Globals Sub so we can have a look at it? Or a subset of it, to give us a clue?
 
Upvote 0

BanditMrP

Member
Licensed User
From memory, it's not just the Globals Sub limited to 64k, it's any Sub.

But it's a pretty big limit to be running into with simple variables.

I vaguely remember a situation with OBDII where we split the big Sub into a few smaller Subs.

Are there any groups of variables that can be combined into one? Like, if you had ten addresses, each with the same fields?

Can you post the entire Globals Sub so we can have a look at it? Or a subset of it, to give us a clue?
Hi Emexes,

There's 3500 lines of Sub Globals, all similar to what I have posted in my original question.

Here for example are the definitions for a couple of very simple screens to do with generating a quote request:

Quote Request from Sub Globals:
    ' ##############################################
    ' Definitions relating to Quote Request Detail 1
    ' ##############################################
    
    Private QRB1_lblSelectionNotice As Label
    Private QRB1_ScrollView1 As ScrollView
        
    Private QRD1_QuoteAttach1Encoded As String
    Private QRD1_QuoteAttach2Encoded As String
    Private QRD1_QuoteAttach3Encoded As String
    
    Private QRD1_QuoteAttach1Filename As String
    Private QRD1_QuoteAttach2Filename As String
    Private QRD1_QuoteAttach3Filename As String

    Private QRD1_AddditionalInfo As EditText
    Private QRD1_Attach1 As Button
    Private QRD1_Attach2 As Button
    Private QRD1_Attach3 As Button
    Private QRD1_CabinetLocation As EditText
    Private QRD1_CabinetType As EditText
    Private QRD1_CancelButton As Button
    Private QRD1_DelAtt1 As Button
    Private QRD1_DelAtt2 As Button
    Private QRD1_DelAtt3 As Button
    Private QRD1_Department As EditText
    Private QRD1_EmailAddress As EditText
    Private QRD1_FaxNumber As EditText
    Private QRD1_IV1 As ImageView
    Private QRD1_IV2 As ImageView
    Private QRD1_IV3 As ImageView
    Private QRD1_JobTime As EditText
    Private QRD1_NextService As RadioButton
    Private QRD1_OnSite As RadioButton
    Private QRD1_PartsRequired As EditText
    Private QRD1_People As EditText
    Private QRD1_RetestNo As RadioButton
    Private QRD1_RetestYes As RadioButton
    Private QRD1_FumigationNo As RadioButton
    Private QRD1_FumigationYes As RadioButton
    Private QRD1_SaveButton1 As Button
    Private QRD1_SerialNumber As EditText
    Private QRD1_ServiceNumber As EditText
    Private QRD1_SiteContact As EditText
    Private QRD1_SpecialVisit As RadioButton
    Private QRD1_Telephone As EditText
    Private QRD1_TimeLeft As EditText
    Private QRD1_Travel As EditText
    Private QRD1_HoldingPanel As Panel
    
    ' ##############################################
    ' Definitions relating to Quote Request Detail 2
    ' ##############################################

    Private QRB2_lblSelectionNotice As Label
    Private QRB2_ScrollView1 As ScrollView
    
    Private QRD2_QuoteAttach1Encoded As String
    Private QRD2_QuoteAttach2Encoded As String
    Private QRD2_QuoteAttach3Encoded As String
    
    Private QRD2_QuoteAttach1Filename As String
    Private QRD2_QuoteAttach2Filename As String
    Private QRD2_QuoteAttach3Filename As String
    
    Private QRD2_SaveButton1 As Button
    Private QRD2_HoldingPanel As Panel
    Private QRD2_AddditionalInfo As EditText
    Private QRD2_CabinetLocation As EditText
    Private QRD2_CabinetType As EditText
    Private QRD2_Department As EditText
    Private QRD2_EmailAddress As EditText
    Private QRD2_FaxNumber As EditText
    Private QRD2_IV1 As ImageView
    Private QRD2_IV2 As ImageView
    Private QRD2_IV3 As ImageView
    Private QRD2_JobTime As EditText
    Private QRD2_NextService As RadioButton
    Private QRD2_OnSite As RadioButton
    Private QRD2_PartsRequired As EditText
    Private QRD2_People As EditText
    Private QRD2_RetestNo As RadioButton
    Private QRD2_RetestYes As RadioButton
    Private QRD2_FumigationNo As RadioButton
    Private QRD2_FumigationYes As RadioButton
    Private QRD2_SerialNumber As EditText
    Private QRD2_ServiceNumber As EditText
    Private QRD2_SiteContact As EditText
    Private QRD2_SpecialVisit As RadioButton
    Private QRD2_Telephone As EditText
    Private QRD2_TimeLeft As EditText
    Private QRD2_Travel As EditText

I've considered re-using some things, but when most of them are views, and could be on screen at the same time (in different tabs), and I need to reference them directly (to save into a database for example), I found that I need to give them distinct names. So you'll see from the above that I have QRD1_Travel and QRD2_Travel both of which are identical EditText views, but both of which could be on screen at the same time.

I'd be interested to know if I can somehow split Sub Globals into more than one Sub if combining as per my original question makes no difference to the compiled code (which I'm guessing is the case).

If splitting Sub Globals can't be done, I'm going to have to drop from my "Easy to read" controls, to save space, such as changing QRD1_SerialNumber to QRD1_SerNo.

Any other suggestions would be greatly appreciated.
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Ok, so you can't split it up into one file for each screen (or tab) because some fields appear in more than one screen (or tab) - is that correct?

Hang on, how could that work: doesn't each field have its own Top and Left? What happens if a field is on multiple screens (or tabs) but presumably at different locations on each?
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Does the:

Java Compile error because it was too large

occur in Release mode, or only in Debug mode?

I don't have B4A set up properly at moment, so I'm experimenting in reproducing the situation in B4J, which I'm pretty sure uses the same Java compiler.

I created 10000 String variables in Globals, and when I compile in Debug mode it comes up with this error:

Log output:
Compiling code.    (1.19s)
Compiling layouts code.    (0.07s)
Organizing libraries.    (0.00s)
Compiling generated Java code.    (3.62s)
Compiling debugger engine code.    Error
shell\src\b4j\example\main.java:9061: error: code too large
  public Object[] GetGlobals() {
                  ^
1 error
only showing the first 1 errors, of 2 total; use -Xmaxerrs if you would like to see more

javac 14.0.1

but when I compile the same code unchanged in Release mode it says:

Log output:
Compiling code.    (0.65s)
Compiling layouts code.    (0.06s)
Organizing libraries.    (0.00s)
Compiling generated Java code.    (3.38s)
Building jar file.    (1.06s)
    Jar file created: E:\b4j\TestLotsOfGlobals\Objects\TestLotsOfGlobals.jar
Running application.    (0.01s)
Completed successfully.
 
Upvote 0

calloatti

Member
Licensed User
Declare a Type structure and use that instead of declaring the same variables with diferent names, or create a class module with the variables declared in the class globals, and then define multiple instances of that class.
 
Upvote 0

BanditMrP

Member
Licensed User
Does the:



occur in Release mode, or only in Debug mode?

I don't have B4A set up properly at moment, so I'm experimenting in reproducing the situation in B4J, which I'm pretty sure uses the same Java compiler.

I created 10000 String variables in Globals, and when I compile in Debug mode it comes up with this error:

Log output:
Compiling code.    (1.19s)
Compiling layouts code.    (0.07s)
Organizing libraries.    (0.00s)
Compiling generated Java code.    (3.62s)
Compiling debugger engine code.    Error
shell\src\b4j\example\main.java:9061: error: code too large
  public Object[] GetGlobals() {
                  ^
1 error
only showing the first 1 errors, of 2 total; use -Xmaxerrs if you would like to see more

javac 14.0.1

but when I compile the same code unchanged in Release mode it says:

Log output:
Compiling code.    (0.65s)
Compiling layouts code.    (0.06s)
Organizing libraries.    (0.00s)
Compiling generated Java code.    (3.38s)
Building jar file.    (1.06s)
    Jar file created: E:\b4j\TestLotsOfGlobals\Objects\TestLotsOfGlobals.jar
Running application.    (0.01s)
Completed successfully.

I couldn't tell you the answer to this, I was working to a deadline, so made enough changes so that I could carry on testing.

Always difficult when on-site and under the spot-light.
 
Upvote 0

BanditMrP

Member
Licensed User
Declare a Type structure and use that instead of declaring the same variables with diferent names, or create a class module with the variables declared in the class globals, and then define multiple instances of that class.

I'm not sure I understand you regarding a type structure. Isn't an EditText a view, and as such if I want to reference it, I need to declare it?

I like the idea of a class module, I'll investigate that further because that sounds like a good solution.
 
Upvote 0

BanditMrP

Member
Licensed User
Ok, so you can't split it up into one file for each screen (or tab) because some fields appear in more than one screen (or tab) - is that correct?

Hang on, how could that work: doesn't each field have its own Top and Left? What happens if a field is on multiple screens (or tabs) but presumably at different locations on each?

I'm not sure you're quite grasping what I'm doing. I have scrollviews on a tabbed interface, and the scrollviews contain a panel full of views. Every scrollview, panel and view has an unique name so I can reference it directly (except for static items such as labels).

A user can have two of the same reports running at the same time in different tabs and there are 8 types of report (some of which have 7+ pages of data to be entered), and I need to be able to reference any control on any tab from any report individually.

I've seen the message above about creating classes for each type of report, and that may be the way to go - I'll investigate that (in a much smaller test app)
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
I'm not sure you're quite grasping what I'm doing.

Thank you for the diplomatic phrasing. To be honest, I am 100% sure I wasn't quite grasping what you're doing - I missed the bit about that it involves ScrollViews too. Not that it should matter.

Splitting the variables (fields, views, elements, whatever they're called) across Classes might well fix the problem.

If you're using LoadLayout then you might want to test earlywith a small subset of your UI, before converting everything to the new way and then finding LoadLayout no longer works.

Are you using B4XPages, or the original B4A activity-based style?
 
Upvote 0

BanditMrP

Member
Licensed User
Thank you for the diplomatic phrasing. To be honest, I am 100% sure I wasn't quite grasping what you're doing - I missed the bit about that it involves ScrollViews too. Not that it should matter.

Splitting the variables (fields, views, elements, whatever they're called) across Classes might well fix the problem.

If you're using LoadLayout then you might want to test earlywith a small subset of your UI, before converting everything to the new way and then finding LoadLayout no longer works.

Are you using B4XPages, or the original B4A activity-based style?
Currently the original B4A Activity-based style.

I'm currently experimenting with Classes to see if I can do what I want (at this point, if I can understand how to do it at all!)
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Currently the original B4A Activity-based style.

I have a feeling that LoadLayout is only going to work with plain old boring Dims in Globals.

So if you're using LoadLayout, check the possible fix as early as you can, before investing too much time applying it to all 3500 lines.
 
Upvote 0

BanditMrP

Member
Licensed User
Please post the error message.

The variables names and the way that they are declared doesn't matter.

That's a shame, does that mean that I have hit a hard limit and need to rethink this completely?

Error Message:
B4A Version: 13.10
Parsing code.    (0.94s)
    Java Version: 19
Building folders structure.    (1.72s)
Compiling code.    (2.51s)
Compiling layouts code.    (0.16s)
Organizing libraries.    (0.42s)
    (AndroidX SDK)
Compiling resources    (3.04s)
Linking resources    (1.07s)
    build tools: 34.0.0, android jar: android-34
Compiling debugger engine code.    Error
shell\src\b4a\WalkersHelpdesk\createreports.java:3704: error: code too large
  public Object[] GetGlobals() {
                  ^
1 error

javac 19.0.2
 
Upvote 0

BanditMrP

Member
Licensed User
That's a shame, does that mean that I have hit a hard limit and need to rethink this completely?

Error Message:
B4A Version: 13.10
Parsing code.    (0.94s)
    Java Version: 19
Building folders structure.    (1.72s)
Compiling code.    (2.51s)
Compiling layouts code.    (0.16s)
Organizing libraries.    (0.42s)
    (AndroidX SDK)
Compiling resources    (3.04s)
Linking resources    (1.07s)
    build tools: 34.0.0, android jar: android-34
Compiling debugger engine code.    Error
shell\src\b4a\WalkersHelpdesk\createreports.java:3704: error: code too large
  public Object[] GetGlobals() {
                  ^
1 error

javac 19.0.2
Now that I've recreated the error, I've tried compiling in release mode, and it compiles fine.

If this is simply a restriction in debug mode then I can work around that.
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
If this is simply a restriction in debug mode then I can work around that.

"code too large" is a restriction that would exist in both Release and Debug modes, but you would reach it first in Debug mode, which generates extra intermediate Java code to support debugging.

You could get an idea of how close you are to the limit by looking at the size of the intermediate *.java (or *.class) files under the Objects project subdirectory, when compiled in Release mode compared to when compiled in Debug mode.
 
Upvote 0

calloatti

Member
Licensed User
I'm not sure I understand you regarding a type structure. Isn't an EditText a view, and as such if I want to reference it, I need to declare it?

I like the idea of a class module, I'll investigate that further because that sounds like a good solution.
B4X:
Type allthevars(lblSelectionNotice As Label, ScrollView1 As ScrollView,......)

Private QR1 as allthevars

Private QR2 as allthevars
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Isn't an EditText a view, and as such if I want to reference it, I need to declare it?

Lol this is why I keep yabbering on about whether you are using LoadLayout or not.

I feel like LoadLayout might only work with "normal" variables declared in the "normal" way and in the "normal" location (Globals).
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0
Top