Android Question Using Multiple Bundles in List

DawningTruth

Active Member
Licensed User
With reference to this post: https://www.b4x.com/android/forum/threads/persist-webview-through-orientation-change.104143/#post-652932

I need to know how to use a list of bundles.

So my current approach is:

B4X:
Sub Process_Globals
    Private Bundle0 As JavaObject
    Private Bundle1 As JavaObject
    Private Bundle2 As JavaObject
    Private Bundle3 As JavaObject
    'etc...

End Sub
This is clearly not a good practice and is in violation of the DRY principle. I would prefer a more elegant solution that uses a list of bundles.

So I created something like this:

B4X:
Sub Process_Globals
   
    'Bundle
    Private bundleList As List
    Private bundle As JavaObject

End Sub

'... Other stuff here

Sub Activity_Pause (UserClosed As Boolean)
   
    bundleList.Initialize
   
    If UserClosed Then
        'User Closed
    Else
        'Save State               
        For n = 0 To webviewList.size -1
            bundle.InitializeNewInstance("android.os.Bundle", Null)
            Dim javaObject_ As JavaObject =  webviewList.get(n)
            javaObject_.RunMethod("saveState", Array(bundle))
            bundleList.Add(javaObject_)
        Next
       
    End If
   
End Sub
However when I implement such a solution I get a java error when I try to restore the webview state:

java.lang.RuntimeException: Method: restoreState not matched.

Can you please advise the correct way to implement a list of bundles.
 

DawningTruth

Active Member
Licensed User
I don't see any call to restoreState.
Thx Erel,

Here is the code for the restore state part. Basically it checks if the bundles are initialized. If so then restores

B4X:
Sub Activity_Create(FirstTime As Boolean)
   
    Log("==============================================")
    Log(">> Activity_Create")
    Log("==============================================")
   
    'Initialization
   
    '... initialise stuff here   
                   
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("MyLayout")
   
    If bundleList.IsInitialized = True Then
        RestoreWebviews
    Else
        CreateWebviews
   End If

End Sub

B4X:
Private Sub RestoreWebviews   

    For n = 0 To WebviewList.size-1
      
       '... View Setup stuff here
        Dim javaObject As JavaObject = webviewView
        javaObject.RunMethod("restoreState", Array(bundleList.Get(n))) 'ERROR Occurs here
   
       '...Other Stuff here

    Next
   
End Sub
 

emexes

Well-Known Member
Licensed User
I feel it is unwise to be reusing Bundle.

Also, what is the underscore in the bundleList.Add(javaObject_) line? That's got a bad vibe about it too.
 

Erel

Administrator
Staff member
Licensed User
This line is wrong:
B4X:
 bundleList.Add(javaObject_)
It should be:
B4X:
 bundleList.Add(bundle)
 

emexes

Well-Known Member
Licensed User
This line is wrong:
B4X:
 bundleList.Add(javaObject_)
It should be:
B4X:
 bundleList.Add(bundle)
Now that I look, there are several other underscores re: javaObject - I'd be removing those too. I'm surprised that the compiler didn't complain more.

Regarding reusing Bundle, I'm still against it from a... directness? perspective, but I imagine that it will work nonetheless, so... if you're happy, then no worries :)
 

DawningTruth

Active Member
Licensed User
I feel it is unwise to be reusing Bundle.

Also, what is the underscore in the bundleList.Add(javaObject_) line? That's got a bad vibe about it too.
Thx Emexes,
Now that I look, there are several other underscores re: javaObject - I'd be removing those too. I'm surprised that the compiler didn't complain more.

Regarding reusing Bundle, I'm still against it from a... directness? perspective, but I imagine that it will work nonetheless, so... if you're happy, then no worries :)
Thx Emexes, the underscores is just my way of reusing the C# convention of: objectName ObjectName where the case type changes for an instance of the object. As that convention does not work with B4A as it is not case sensitive, and I personally don't like naming like: ObjectName1 As ObjectName I just put in an underscore and it works perfectly fine, and avoid the cognitive load of having to think up a variable name for an instance.

As to the bundles, the original suggested code from Erel uses a bundle. He suggested I use multiple bundles for more than one WebView. This works like the bomb. However, the problem is that I need to have a whole lot of bundles named like: Bundle1, Bundle 2 etc... this is not the way I like to code as it is inelegant. So, I'm trying to figure out how to create a List of Bundle Objects. That is what the code is.
 

DawningTruth

Active Member
Licensed User
This line is wrong:
B4X:
 bundleList.Add(javaObject_)
It should be:
B4X:
 bundleList.Add(bundle)
Thx Erel, this worked.

Clearly there is something missing in my understanding. Can you please explain why you add the bundle to the list and not the Java Object. In my mind the bundle gets added to the Java Object, which is then added to the list. Obviously this understanding is incorrect.
 
Last edited:

emexes

Well-Known Member
Licensed User
I just put in an underscore and it works perfectly fine
Fair enough, just watch out that in many BASIC dialects an underscore at the end of a line will continue that line with the next line.
avoid the cognitive load of having to think up a variable name for an instance
Yeah, I thought you couldn't use type names as variable names, but just yesterday I used Dim Xui as XUI (copied from somebody else's code) and it worked (much to my surprise). Maybe it only works for class:instance and not for type:variable. Makes me nervous still. I usually just imagine what adjective I'd use for the instance I'm creating now, if I were to have other different instances later, so here I'd probably Dim WebViewBundle As Bundle, or more likely Dim SavedWebView As Bundle.

Anyway, that's enough esoteric programming style discussion - this is a get stuff done forum :)
This works like the bomb.
:)
create a List of Bundle Objects
From what I saw of your code, your extending Erel's save-one-webview-to-one-bundle to the required save-list-of-webviews-to-list-of-bundles was almost there. I thought it was the underscores that were gumming up the works. Does it still not work after those have been removed?
 

DawningTruth

Active Member
Licensed User
Fair enough, just watch out that in many BASIC dialects an underscore at the end of a line will continue that line with the next line.
Interesting point. I have not had an issue so far, but something to be aware of.

Anyway, that's enough esoteric programming style discussion - this is a get stuff done forum :)
Yes, but still interesting to learn how other people tackle the same challenge. I'm quite heavily influenced by C# and C++ so tend to prefer to use those conventions, which does not always neatly translate to other languages. :) I'm also a get it done type, hence why I like B4x.

Does it still not work after those have been removed?
The underscores weren't the issue. I was adding the Java Object to the list instead of the bundle.:rolleyes: There is a gap in my understanding which I have asked Erel to explain.
 

emexes

Well-Known Member
Licensed User
How about:
B4X:
Private Sub RestoreWebviews   

    For n = 0 To WebviewList.Size - 1    'hopefully BundleList is same size...
      
       '... View Setup stuff here
        Dim jo As JavaObject = WebviewList.Get(n)    'was previously: = webviewView

        jo.RunMethod("restoreState", Array(BundleList.Get(n)))
   
       '...Other Stuff here

    Next   
End Sub
 

DawningTruth

Active Member
Licensed User
I think it's more like the bundle IS a Java Object
B4X:
Private bundle As JavaObject
Ok thx, now I get it. Sometimes I want to kick myself for these misunderstandings that should be obvious, but Android and Java are very complex. And this complexity overloads the mind. There is a reason why so many Java projects are late and over budget.
 

DawningTruth

Active Member
Licensed User
How about:
B4X:
Private Sub RestoreWebviews 

    For n = 0 To WebviewList.Size - 1    'hopefully BundleList is same size...
    
       '... View Setup stuff here
        Dim jo As JavaObject = WebviewList.Get(n)    'was previously: = webviewView

        jo.RunMethod("restoreState", Array(BundleList.Get(n)))
 
       '...Other Stuff here

    Next 
End Sub
Yes, that is an approach that Erel uses in most of his examples. Personally I find it harder to work with variable names that use acronyms. It increases the cognitive load as I have to now remember what the acronym stands for. As my app has so many moving parts and is so complex featuring complexities within complexities within complexities, and that is after refactoring, I try to minimize as much cognitive load as possible so I only have to focus on algorithm.

Perhaps this is just me, as everyone else on the Forum seems to actually prefer this way of working.:)
 

emexes

Well-Known Member
Licensed User
I think that bit was ok. You had a Bundle (As JavaObject) which you used to save the Webview state, and then added to BundleList.
My only gripe was that you were reusing Bundle rather than Dim'ng up a new one for each saved Webview, but I think you dodged a bullet there ;-) saved by the .InitializeNewInstance

If you were a cat, I'd say you'd just used one of your nine lives...
 

DawningTruth

Active Member
Licensed User
My only gripe was that you were reusing Bundle rather than Dim'ng up a new one for each saved Webview, but I think you dodged a bullet there ;-) saved by the .InitializeNewInstance

If you were a cat, I'd say you'd just used one of your nine lives...
Yes, agreed. Normally I do it that way, I have made the change you are suggesting as it is a better and more robust approach.
 

emexes

Well-Known Member
Licensed User
Personally I find it harder to work with variable names that use acronyms. It increases the cognitive load as I have to now remember what the acronym stands for.
I only use names like jo when it's a temporary variable within just a few lines of code. And if I do reuse the same name elsewhere in the code, then I Dim it to emphasize that this is the point where it is starting afresh.

Should probably mark the end point with something like: jo = null

Yeah, miss the {} scoping blocks of C et al.
 

DawningTruth

Active Member
Licensed User
I only use names like jo when it's a temporary variable within just a few lines of code. And if I do reuse the same name elsewhere in the code, then I Dim it to emphasize that this is the point where it is starting afresh.

Should probably mark the end point with something like: jo = null

Yeah, miss the {} scoping blocks of C et al.
Thx for the tip :)
 
Top