Android Question Null not evaluating as Null

Computersmith64

Well-Known Member
Licensed 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.
 

DonManfred

Expert
Licensed User
Upvote 0

Star-Dust

Expert
Licensed User
if it returns "null" then the result is a String
object null cast a string = "Null"

ExecQuerySingleResult null passed as string paeameter became "Null"

He make:
B4X:
 Private icon As String = Starter.sqlDB.ExecQuerySingleResult2("SELECT GroupIcon FROM tblGroups WHERE GroupName=?", ArrayAsString(group))
 
Upvote 0

Star-Dust

Expert
Licensed User
My wish - Ternary operators :D:D

B4X:
Private icon AsString = Starter.sqlDB.ExecQuerySingleResult2("SELECT GroupIcon FROM tblGroups WHERE GroupName=?", ArrayAsString(group))==Null?"":Starter.sqlDB.ExecQuerySingleResult2("SELECT GroupIcon FROM tblGroups WHERE GroupName=?", ArrayAsString(group))
 
Upvote 0

Star-Dust

Expert
Licensed User
Other solution
B4X:
Private icon As String = Starter.sqlDB.ExecQuerySingleResult2("SELECT GroupIcon FROM tblGroups WHERE GroupName=?", ArrayAsString(group)).Replace(Null,"standard_icon.png")
 
Last edited:
Upvote 0

Erel

Administrator
Staff member
Licensed User
Returning Null from a library when the return value is a String is a mistake as Null is a tricky value for strings.

When you write:
B4X:
Dim s As String = Null
The Null object is converted to a string and the value of s will be "null". It is not the same as a Null value returned from a library.

Your code should be:
B4X:
Public Sub getMarkerIcon(icon As String) As Bitmap
    Private iconImg As Bitmap
  
    If icon <> Null AND icon <> "" Then
        iconImg.Initialize(File.DirAssets, icon)
    Else
        iconImg.Initialize(File.DirAssets, "icon_default.png")
    End If
  
    Return CreateScaledBitmap(iconImg, 25dip, 25dip)
End Sub
Pass an empty string in your code instead of Null.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Returning Null from a library when the return value is a String is a mistake as Null is a tricky value for strings.

Thanks Erel. Interesting statement though, because here's the code from the B4J library on GitHub:

B4X:
public String ExecQuerySingleResult2(String Query, List Args) throws SQLException {
    checkNull();
    ResultSetWrapper cursor = ExecQuery2(Query, Args);
    try {
        if (!cursor.NextRow())
            return null;
        if (cursor.getColumnCount() == 0)
            return null;
        return cursor.GetString2(0);
    } finally {
        cursor.Close();
    }
}

It seems that the library does exactly that.

- Colin.
 
Upvote 0

Erel

Administrator
Staff member
Licensed User
It seems that the library does exactly that.
That's true. Mistakes happen.

It would have been better to return an empty string instead, however the behavior of this method cannot be changed without making a breaking change (and the issue is not so significant that it justifies making a breaking change).
 
Upvote 0

netsistemas

Active Member
Licensed User
I have this function beacause in SQLITE you can get NULL text too, and ... .. .. .


Insert in MODULE and enjoit!!

Public Sub IsNull(Valor As String ) As Boolean
If Valor = Null Then
Return True
Else
If Valor.Trim.ToUpperCase = "NULL" Then
Return True
Else
Return False
End If
End If
End Sub
 
Upvote 0

Star-Dust

Expert
Licensed User
It is better to use objects instead of string

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