B4J Question Passing "map" as parameter

MM2forever

Active Member
Licensed User
I know this seems a pretty basic question and I don't really know whats going on. Searched the forums for quite a while tough...

I am trying to pass a map object to a function that uses items of the map like this:

B4X:
Private Sub AddToList(event As Map)
    Dim string1 As String

    string1 = event.Get("Name") & " | "
    string1 = string1 & event.Get("Time") & " | "
    string1 = string1 & NumberFormat(Bit.ToBinaryString(event.Get("Days")),8,0) & " | "
    string1 = string1 & event.Get("MQTTTopic") & " | "
    string1 = string1 & event.Get("MQTTVal")
    Main.Eventlistview.Items.Add(string1)
End Sub
now the argument that gets passed emerges from, an iteration over another map that holds maps like the one thats supposed to get passed:
B4X:
For i=0 To eventdb.Size-1
       AddToList(eventdb.GetValueAt(i))
Next
What happens is that the program goes crashing with that:
"java.lang.ClassCastException: java.lang.String cannot be cast to anywheresoftware.b4a.objects.collections.Map$MyMap"

I tried a bunch of tricks like passing it as "object" and then assigning it to an initialized temporary map but nothing works.
I have to admit I'm neither very skilled in nor very fond of OOP, I just recently started to get deeper into OOP using B4J to at least keep an open mind about it, so please be gentle.

Help is much appreciated!
Thank you guys
 

Daestrum

Well-Known Member
Licensed User
In this code what is logged if you change it to
B4X:
For i=0 To eventdb.Size-1
       Log(GetType(eventdb.GetValueAt(i))
       'AddToList(eventdb.GetValueAt(i))
Next
I suspect the problem is caused where you add the item to the map eventdb.
If the above code logs String or java.lang.String, then you are adding the string representation of the identifier of the map instead of the actual map.
 

Harris

Expert
Licensed User
Assuming the Key is a String and the Value is a map...

B4X:
' if value is a map

For Each key As String In eventdb.Keys  ' for each key, value pair in the eventdb map
 
  Dim Mp as Map = eventdb.Get(key)  ' get value as map
  AddToList(Mp)   ' add the map

Next
As Erel suggests, don't use .GetValueAt - Only exists for backwards compatibility..
 
Last edited:

MM2forever

Active Member
Licensed User
In this code what is logged if you change it to
B4X:
For i=0 To eventdb.Size-1
       Log(GetType(eventdb.GetValueAt(i))
       'AddToList(eventdb.GetValueAt(i))
Next
I suspect the problem is caused where you add the item to the map eventdb.
If the above code logs String or java.lang.String, then you are adding the string representation of the identifier of the map instead of the actual map.
Im also suspecting this as well now and the recommendation by Harris gives the same error.

Doing the "GetType" logging infact returns "java.lang.String" and simply logging the value gives the map contents as a string as it would be saved to a file.

the eventdb gets filled here:

B4X:
Public Sub add(eventname As String, eventtime As String, eventdays As Int, eventtopic As String, eventval As String)
    Dim event As Map
    event.Initialize
    
    event.Put("Name",eventname)
    event.Put("Time",eventtime)
    event.Put("Days",eventdays)
    event.Put("MQTTTopic",eventtopic)
    event.Put("MQTTVal",eventval)
    
    eventdb.Put(eventname, event)
    AddToList(event)
End Sub
The funny thing is when "AddToList" is called there, it makes no problem at all, only if it comes from the map in the other function. What am I doing wrong when I "eventdb.Put()"-it? Why does it get a String representation?
I also thought that having a Prototype as
Private Sub AddToList(event As Map)
would kind of try to cast it to be a map then...
 

Daestrum

Well-Known Member
Licensed User
This seems to work OK, just minor changes from your original code
B4X:
 Dim eventdb As Map
 Dim eventlistview As ListView
End Sub
Sub AppStart (Form1 As Form, Args() As String)
 MainForm = Form1
 'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
 MainForm.Show
 eventlistview.Initialize("")
 MainForm.RootPane.AddNode(eventlistview,10,10,400,500)
 eventdb.Initialize
 ' some dummy data
 add("one","12:00",3,"Topic1","Val1")
 add("two","13:00",4,"Topic2","Val2")
 add("three","15:00",6,"Topic3","Val3")
' add individual maps by name
 AddToList("one")
 AddToList("three")
 ' or  add all maps
 For Each k As String In eventdb.Keys
  AddToList(k)
 Next
End Sub
Public Sub add(eventname As String, eventtime As String, eventdays As Int, eventtopic As String, eventval As String)
 Dim event As Map
 event.Initialize
    
 event.Put("Name",eventname)
 event.Put("Time",eventtime)
 event.Put("Days",eventdays)
 event.Put("MQTTTopic",eventtopic)
 event.Put("MQTTVal",eventval)
    
 eventdb.Put(eventname, event)
End Sub
Private Sub AddToList(key As String)
  Dim event As Map = eventdb.Get(key)
  Dim string1 As String
  string1 = event.Get("Name") & " | "
  string1 = string1 & event.Get("Time") & " | "
  string1 = string1 & NumberFormat(Bit.ToBinaryString(event.Get("Days")),8,0) & " | "
  string1 = string1 & event.Get("MQTTTopic") & " | "
  string1 = string1 & event.Get("MQTTVal")
  eventlistview.Items.Add(string1)
End Sub
 

MM2forever

Active Member
Licensed User
I got the feeling that I left out an important part of the puzzle because until now I thought it wouldn't matter...
The eventdb map is saved to a file and the error occurs at program start after everything is supposedly loaded back from that file:
B4X:
Public Sub save
    File.WriteMap(File.DirApp,"schedule.map",eventdb)
End Sub

Public Sub load
    If File.Exists(File.DirApp,"schedule.map") Then
        eventdb = File.ReadMap(File.DirApp,"schedule.map")

        For i=0 To eventdb.Size-1
            AddToList(eventdb.GetValueAt(i))
        Next

    End If
End Sub
So File.WriteMap / Readmap does not preserve Object type and makes everything a string? How would I correctly save a map of any object then?

Edit:
I now used the Map2Json / Json2Map functions as pointed out here: Save Map To KeyValueStore, Load Map From KeyValueStore

Now it works. Which means my problem emerged reading back the map and if I would have gotten the saving right my initial code would have worked all along. Sorry guys...
 
Last edited:

Harris

Expert
Licensed User
Now it works. Which means my problem emerged reading back the map and if I would have gotten the saving right my initial code would have worked all along. Sorry guys...
It is very important that you post your complete code! Not just snippets.
We, on the other other end, trying to help, have to try and figure out what the heck you are doing?

This happens so often, and I don't know why? When the community can look at the overall code base - they can usually see the error in the way...

This frustrates everyone trying to reach out and help. It end up a guessing game.
Others, looking at your post will (rightfully so) not respond.. since it leads down the endless road of trying to interpret what the heck you are implying, asking questions and never getting an appropriate response... So - they give up - and can detect your request (lacking info) - and never help.

Not a slant against you, or anyone... Just don't keep us guessing when you (anyone) can fully inform!

We are not mind readers... (yet I think Erel is - cause he has special powers - which we can not contest / comprehend).
 
Last edited:

Harris

Expert
Licensed User
I was was also going to state that your biggest supporter on this site, @DonManfred,(expert) would hesitate to respond. He has been down this path far too many times in the past - and could see where this would lead him... an endless tunnel where you don't want to go - else reap the wrath - of trying keeping all of us on track...
If YOU can't inform, neither can he (we)... His endless mantra (and rightfully so).

In conclusion, give us complete info to help you. PLEASE - Don't waste our time trying to guess what you have done or imply. Supply all!
Resolutions can often be resolved in 2 posts, rather than endless back and forth...


Thanks
 

MM2forever

Active Member
Licensed User
@Harris

I totally get your point and I dont feel attacked at all. Thats basically what I excused for when I said "Sorry guys" earlier on.
I have spent a lot of time on many different forums in the past 15 years, much more active in the beginning.
As far as I see it tough its always a balancing act between posting "too few code" which causes those problems we had in my thread right here
and posting "just everything" which (in many forums) gives a big frown by everyone as well because it sometimes gives the idea the the OP wants others to just solve their code and not think it trough as well.
 

Harris

Expert
Licensed User
@MM2forever ,

Sorry I ranted like that. I was in an off state and just couldn't help myself. I get that way sometimes... Too high on my horse and mighty.
I agree with your explanation.

Sorry to all, I shall try and contain myself going forward. Hopefully I can be forgiven.
 

MM2forever

Active Member
Licensed User
@Harris, really mate it's okay. You got points as well and I know all to well that at some point you just snap. I dont judge that to much, I never know how the other ones day went tough and I know we are just humans after all.

I like to think that our little detour finding the solution still had a purpose, I mean at least it made me think about it deeper and I was lying in my bed yesterday morning and realised it had to to with the loading from the file. And I think the important part to learn is - at least trace back to where the data comes from that causes the error and post that.

I mean the rest of my code is way larger and has nothing todo with the issue... the main skill when looking for help is to know whats important to the problem I guess.
 
Top