Android Question ForEach loop to access custom type?

Arf

Well-Known Member
Licensed User
Longtime 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
Longtime 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.
 
Upvote 0

Arf

Well-Known Member
Licensed User
Longtime 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.
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime 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
 
Upvote 0

Brian Robinson

Active Member
Licensed User
Longtime 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
 
Upvote 0

Brian Robinson

Active Member
Licensed User
Longtime 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
 
Upvote 0

Arf

Well-Known Member
Licensed User
Longtime 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!
 
Upvote 0
Top