Android Question Null not evaluating as Null

Computersmith64

Well-Known Member
Licensed User
Longtime User
Upfront disclaimer: I've been working on my latest project pretty hard for the past few weeks, so I'm getting very tired...

I have a sub that takes a String argument & returns a bitmap. I perform a test on the string to see if it's Null & if it isn't loads the file in the string, else it loads a default image:
B4X:
'In my AppUtils module
Public Sub getMarkerIcon(icon As String) As Bitmap
    Private iconImg As Bitmap
   
    If icon <> Null Then 
        iconImg.Initialize(File.DirAssets, icon) 
    Else 
        iconImg.Initialize(File.DirAssets, "icon_default.png")
    End If
   
    Return CreateScaledBitmap(iconImg, 25dip, 25dip)
End Sub

I call this function from a couple of different places in my Main activity. In one call I use the result from a query & in the other I just pass Null, or a String set to Null.
B4X:
    Private icon As String = Starter.sqlDB.ExecQuerySingleResult2("SELECT GroupIcon FROM tblGroups WHERE GroupName=?", Array As String(group))
    Private m1 As Marker = gmap.AddMarker3(lat, lon, title, AppUtils.getMarkerIcon(icon))

'AND

    Private m1 As Marker = gmap.AddMarker3(lat, lon, title, AppUtils.getMarkerIcon(Null))
'OR
    Private icon as String = Null
    Private m1 As Marker = gmap.AddMarker3(lat, lon, title, AppUtils.getMarkerIcon(icon))

So here's the problem. In the first call (where "icon" is the result of the query) if the query returns Null, it works fine - BUT - if I pass Null, the If statement evaluates to true & the app crashes.

According to the documentation, the return type from ExecQueryResult2 is either a String, or Null. The variable ("icon") receiving the return value from the query is a String. Even if I declare a String, assign Null to it & then pass it to the sub, it still crashes. If I change the sub argument type to Object, it works fine.

Why does it work when a String that has been set to Null by ExecQuerySingleResult2 is passed, but not when a String that has been set to Null (or just Null) is passed?

- Colin.
 

Star-Dust

Expert
Licensed User
Longtime User
I solved every problem as I did:

B4X:
Public Sub getMarkerIcon(icon As String) As Bitmap
    Private iconImg As Bitmap
  
    Try
        iconImg.Initialize(File.DirAssets, icon)
    Catch
        iconImg.Initialize(File.DirAssets, "icon_default.png")
    End Try
  
    Return CreateScaledBitmap(iconImg, 25dip, 25dip)
End Sub

So no matter what returns, null or empty ... goes wrong and passes to the standard image
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
I solved every problem as I did:

B4X:
Public Sub getMarkerIcon(icon As String) As Bitmap
    Private iconImg As Bitmap

    Try
        iconImg.Initialize(File.DirAssets, icon)
    Catch
        iconImg.Initialize(File.DirAssets, "icon_default.png")
    End Try

    Return CreateScaledBitmap(iconImg, 25dip, 25dip)
End Sub

So no matter what returns, null or empty ... goes wrong and passes to the standard image
Yep - that will work, as does changing "icon As String" to "icon As Object" - but I'm still keen to know why it doesn't work when icon is declared as a String...

I know that Erel will probably have a perfectly logical explanation as to why. I'd like to know what it is!

- Colin.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
I like this
B4X:
Public Sub getMarkerIcon(iconfile As String) As Bitmap
   Try
      Return CreateScaledBitmap(LoadBitmap(File.DirAssets, iconfile), 25dip, 25dip)
   Catch
      Return CreateScaledBitmap(LoadBitmap(File.DirAssets, "icon_default.png"), 25dip, 25dip)
   End Try
End Sub
 
Last edited:
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Add Log(IconFile)
so can see what return

Yep - that will work, as does changing "icon As String" to "icon As Object" - but I'm still keen to know why it doesn't work when icon is declared as a String...

I know that Erel will probably have a perfectly logical explanation as to why. I'd like to know what it is!

- Colin.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Add Log(IconFile)
so can see what return
It's not the return value that's the problem - it's the value of "icon". When it's declared as a String & I pass Null to it, the statement:

B4X:
    If icon <> Null

evaluates to True - even though when I put a Log(icon) statement before it the log shows Null.

- Colin.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Icon=Null or icon="Null", becouse is different
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
I lime this
B4X:
Public Sub getMarkerIcon(iconfile As String) As Bitmap
   Try
      Return CreateScaledBitmap(LoadBitmap(File.DirAssets, iconfile), 25dip, 25dip)
   Catch
      Return CreateScaledBitmap(LoadBitmap(File.DirAssets, "icon_default.png"), 25dip, 25dip)
   End Try
End Sub

Also - my preference is not to write code that will intentionally trigger an exception. There are times when it is acceptable to pass Null to this sub so I don't want to trigger an exception every time I do. :)

- Colin.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Try also
If isNull(icon) Then
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Icon=Null or icon="Null", becouse is different
Yes - I'm aware of that. The result of the query generates either a String or Null (not "Null") & I am passing Null (not "Null").

- Colin.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Now Exist :p:p:p:p

B4X:
Sub IsNull(O as Object) ad Boolean
     Return (O=Null)
End Sub
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Also - my preference is not to write code that will intentionally trigger an exception. There are times when it is acceptable to pass Null to this sub so I don't want to trigger an exception every time I do. :)

- Colin.

This is your preference, but sometimes managing exceptions appears to be the most practical solution is more reasonable. That does not make you waste precious time
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Now Exist :p:p:p:p

B4X:
Sub IsNull(O as Object) ad Boolean
     Return (O=Null)
End Sub
Yeah - but I can achieve the same thing by just declaring:
B4X:
    Public Sub getMarkerIcon(icon as Object) as Bitmap

So I already have a workaround, but I want to know why Null evaluates differently between 2 different strings. What is is that makes ExecQuerySingleResult return a "true" Null, but passing Null doesn't work?

- Colin.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
This is your preference, but sometimes managing exceptions appears to be the most practical solution is more reasonable. That does not make you waste precious time
I use Try Catch End Try blocks in my code all the time to catch unintended exceptions - but I don't like intentionally triggering them. I'd rather write code that only triggers exceptions when something unanticipated happens.

- Colin.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Yes - I'm aware of that. The result of the query generates either a String or Null (not "Null") & I am passing Null (not "Null").

- Colin.
I had posed with the question specifically because often I also found that the string assumes the "Null" value ;)
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Thanks - that does explain why assigning Null to a string doesn't work (because it gets converted to "Null"), but it doesn't explain how ExecQuerySingleResult is able to assign Null to a string variable without it being converted to a string.

- Colin.
Probably the value that returns ExecQuerySingleResult is not a string but an object, because it could also return a numeric value, or any other type contained in the database
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Probably the value that returns ExecQuerySingleResult is not a string but an object, because it could also return a numeric value, or any other type contained in the database
That could be true, in which case the documentation is incorrect because it states that the return type is String.

- Colin.
 
Upvote 0
Top