Android Question ForEach loop to access custom type?

Arf

Well-Known Member
Licensed User
I have created a type which is an array of Shorts, which I need to populate with data received via bluetooth. The type contains many more entries than what I have put in below:
B4X:
Type PktResults(RV1 As Short, RV2 As Short, RV3 As Short, RV4 As Short)
In order to unpack the contents of an array into this structure, I am trying to do this:
B4X:
Dim ref As Byte = 0
                For Each n As Short In ForcedTest.Results
                    n = Bit.Xor(pData(ref)*256,ByteToInt(pData(ref+1)))
                    ref = ref+2
                Next
But I am getting a compilation error:
src\SpiroConnect\Home\unit_comms.java:690: error: incompatible types
final anywheresoftware.b4a.BA.IterableList group291 = mostCurrent._forcedtest._results;
required: IterableList
found: _pktresults

I understand that the error is because my type is not an array as such.
Is there a different loop type or method that I can use to access each element of my type in a looping manner?

Thanks
 

Arf

Well-Known Member
Licensed User
I guess I could create a local list to do the loop populating, then copy the list into the type.
So if I create an array of shorts (or a list of shorts), would I be able to easily copy the contents into my type?

I am so used to C and pointers, I get really stuck with shifting data about without them.
 

Arf

Well-Known Member
Licensed User
Well the reason for the type is that there are 75 parameters in that type, they're actually medical indices with names like FEV1, FVC, FEV6, FEV3_FVC etc.. I need to access these individual parameters at many points throughout my program, and so to best avoid making mistakes, I want to be able to access them using their 'names', ie
ForcedExpiratoryRatio = Results.FEV1/Results.FVC
rather than
ForcedExpiratoryRatio = Results(11)/Results(32)
as it's just so much easier to find mistakes.

I suppose enumerating the indice names to access the elements by name is an idea.
 

thedesolatesoul

Expert
Licensed User
I see your point.

The most TypeSafe way is indeed a custom type.
A map would be better than a list, but it still wont be as safe, as Maps hold objects that can be re-cast.

One (very long) method is to create a class. Store the items in a map, but always ensure to TypeCast them back to Short whenever you Get/Set them.

B4X:
Sub Class_Globals
     Private PktResultMap as Map
End Sub

Sub GetFEV1 as Short
     Dim retItem as Short = PktResultMap.Get("FEV1")
     Return retItem
End Sub

Sub SetFEV1(pFEV1 as Short)
     PktResultMap.Set("FEV1", pFEV1)
End Sub
 

Brian Robinson

Active Member
Licensed User
I know it's not the best solution. But maybe constants? It would be less expensive that having to iterate each time to find the name.

Or maybe write the results into a Map with the variable name as the key? The hash of the map would be quicker to get the results.

Cheers
Brian
 

Brian Robinson

Active Member
Licensed User
I see your point.

The most TypeSafe way is indeed a custom type.
A map would be better than a list, but it still wont be as safe, as Maps hold objects that can be re-cast.

One (very long) method is to create a class. Store the items in a map, but always ensure to TypeCast them back to Short whenever you Get/Set them.

B4X:
Sub Class_Globals
     Private PktResultMap as Map
End Sub

Sub GetFEV1 as Short
     Dim retItem as Short = PktResultMap.Get("FEV1")
     Return retItem
End Sub

Sub SetFEV1(pFEV1 as Short)
     PktResultMap.Set("FEV1", pFEV1)
End Sub
Hmmm.. Never thought of doing that... That is a great way to force some level of Type Safety. I must admit I have been very lazy when using B4A and not worrying about keeping things safe and in some way enjoying the freedom. After all most of the apps I have written are quite small in size.

Cheers
Brian
 

Arf

Well-Known Member
Licensed User
Ok, got it doing what I want using the poor man's enums:

B4X:
Type PktResults(Index(48) As Short)
'enumerate the indice names
Dim Const VC=0,FEV075=1, FEV1=2,FEV3=3 etc
'fill the type with received data
Dim ref As Byte = 0
                Dim n As Byte = 0
                'For Each n As Element In ForcedTest.Results
                Do While n < 48               
                    ForcedTest.Results.Index(n) = Bit.Xor(pData(ref)*256,ByteToInt(pData(ref+1)))
                    ref = ref+2
                    n = n+1
                Loop
'work with the indices by name
If Results.Index(PEF) > 1000 OR Results.Index(FVC) > 600 Then
blah blah blah
In the case of this product, all the results are determined inside a seperate bit of equipment, the tablet is just used to present the results.
It's also not dangerous if things go wrong - which is no excuse for things going wrong!
 
Top