I have 2 classes, FirebaseAuth and GoogleSheetsAPI.
In B4XMainPage, I initialized the objects and call the methods.
In FirebaseAuth:
In GoogleSheetAPI:
I think I am facing a race condition.
I am not familiar with such callback calling so I am seeking help to understand the prolem.
In B4XMainPage, I initialized the objects and call the methods.
B4XMainPage:
Sub Class_Globals
Private api As GoogleSheetsAPI
Private auth As FirebaseAuth
End Sub
Public Sub Initialize
'B4XPages.GetManager.LogEvents = True
api.Initialize(Me, "SheetManager")
auth.Initialize(Me, "Auth")
End Sub
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Root.LoadLayout("MainPage")
auth.SignInAnonymously
End Sub
In FirebaseAuth:
FirebaseAuth:
Sub Class_Globals
Private EventName As String
Private Callback As Object
End Sub
Public Sub Initialize (CallbackModule As Object, EventNameStr As String)
Callback = CallbackModule
EventName = EventNameStr
tmrRefresh.Initialize("tmrRefresh", 300000) '5 minutes
End Sub
'Resumable sub
Public Sub SignInAnonymously
Dim job As HttpJob
job.Initialize("", Me)
job.PostString(AUTH_BASE & FIREBASE_API_KEY, body)
job.GetRequest.SetHeader("Content-Type", "application/json")
Wait For (job) JobDone(job As HttpJob)
If job.Success Then
Dim response As String = job.GetString
' the rest of code
CallSubDelayed3(Callback, EventName & "_AuthComplete", True, "")
CallSubDelayed3(Callback, EventName & "_TokenResult", token, "")
Else
CallSubDelayed3(Callback, EventName & "_AuthComplete", False, msg)
CallSubDelayed3(Callback, EventName & "_TokenResult", "", msg)
End If
job.Release
End Sub
In GoogleSheetAPI:
GoogleSheetAPI:
Sub Class_Globals
Private EventName As String
Private Callback As Object
#If B4J
Private BaseURL As String = "http://127.0.0.1:8080/api"
#Else
Private BaseURL As String = "https://your-backend.com/api"
#End If
Private AuthToken As String
End Sub
Public Sub Initialize (CallbackModule As Object, EventNameStr As String)
Callback = CallbackModule
EventName = EventNameStr
End Sub
Public Sub LoadData (SheetID As String)
Dim url As String = BaseURL & "/sheets/" & SheetID
SendRequest("LOAD", url, "")
End Sub
Public Sub AddRecord (SheetID As String, Name As String, Email As String, Phone As String)
Dim url As String = BaseURL & "/sheets/" & SheetID
Dim json As String = CreateJSON(Name, Email, Phone)
SendRequest("ADD", url, json)
End Sub
Private Sub SendRequest (Tag As String, Url As String, PostData As String)
Log($"SendRequest(${Tag}, ${Url}, ${PostData})"$)
If TokenEmpty Then Return
Dim job As HttpJob
job.Initialize(Tag, Me)
Select Tag
Case "LOAD"
job.Download(Url)
Case "ADD", "UPDATE", "CREATE"
job.PostString(Url, PostData)
Case "DELETE"
job.PostString(Url, "")
Dim req As JavaObject = job.GetRequest
req.RunMethod("setRequestMethod", Array("DELETE"))
End Select
job.GetRequest.SetHeader("Authorization", "Bearer " & AuthToken)
job.GetRequest.SetHeader("Content-Type", "application/json")
Log("Request: " & Tag & " -> " & Url)
Wait For (job) JobDone(job As HttpJob)
ParseResponse(job, Tag)
job.Release
End Sub
Private Sub ParseResponse (Job As HttpJob, Tag As String)
If Job.Success Then
Dim response As String = Job.GetString
Log($"(${Tag}) Response: ${response}"$)
Try
Dim root As Map = response.As(JSON).ToMap
Dim success As Boolean = root.GetDefault("success", False)
Dim errorMsg As String = root.GetDefault("error", "")
If success Then
Select Tag
Case "LOAD"
Dim data As List
If root.ContainsKey("data") Then
Dim rawData As List = root.Get("data")
data.Initialize
For Each item As Map In rawData
Dim row As Map
row.Initialize
row.Put("ID", item.GetDefault("id", ""))
row.Put("Name", item.GetDefault("name", ""))
row.Put("Email", item.GetDefault("email", ""))
row.Put("Phone", item.GetDefault("phone", ""))
data.Add(row)
Next
Else
data.Initialize
End If
Dim m As Map
m.Initialize
m.Put("success", True)
m.Put("data", data)
m.Put("error", "")
CallSubDelayed2(Callback, EventName & "_DataLoaded", m)
Case "ADD"
Dim record As Map
If root.ContainsKey("data") Then
record = root.Get("data")
Else
record.Initialize
End If
Dim m As Map
m.Initialize
m.Put("success", True)
m.Put("record", record)
m.Put("error", "")
CallSubDelayed2(Callback, EventName & "_RecordAdded", m)
Case "UPDATE"
CallSubDelayed3(Callback, EventName & "_RecordUpdated", True, "")
Case "DELETE"
CallSubDelayed3(Callback, EventName & "_RecordDeleted", True, "")
Case "CREATE"
Dim sheetID As String = root.GetDefault("sheetId", "")
Dim m As Map
m.Initialize
m.Put("success", True)
m.Put("sheetId", sheetID)
m.Put("error", "")
CallSubDelayed2(Callback, EventName & "_SheetCreated", m)
End Select
Else
Select Tag
Case "LOAD"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("data", Null)
m.Put("error", errorMsg)
CallSubDelayed2(Callback, EventName & "_DataLoaded", m)
Case "ADD"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("record", Null)
m.Put("error", errorMsg)
CallSubDelayed2(Callback, EventName & "_RecordAdded", m)
Case "UPDATE"
CallSubDelayed3(Callback, EventName & "_RecordUpdated", False, errorMsg)
Case "DELETE"
CallSubDelayed3(Callback, EventName & "_RecordDeleted", False, errorMsg)
Case "CREATE"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("sheetId", "")
m.Put("error", errorMsg)
CallSubDelayed2(Callback, EventName & "_SheetCreated", m)
End Select
End If
Catch
Log("Parse error: " & LastException.Message)
Select Tag
Case "LOAD"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("data", Null)
m.Put("error", "Invalid server response")
CallSubDelayed2(Callback, EventName & "_DataLoaded", m)
Case "ADD"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("record", Null)
m.Put("error", "Invalid server response")
CallSubDelayed2(Callback, EventName & "_RecordAdded", m)
Case "UPDATE"
CallSubDelayed3(Callback, EventName & "_RecordUpdated", False, "Invalid server response")
Case "DELETE"
CallSubDelayed3(Callback, EventName & "_RecordDeleted", False, "Invalid server response")
Case "CREATE"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("sheetId", "")
m.Put("error", "Invalid server response")
CallSubDelayed2(Callback, EventName & "_SheetCreated", m)
End Select
End Try
Else
LogColor($"(${Tag}) HTTP error: ${Job.ErrorMessage}"$, 0xFFFF0000)
Select Tag
Case "LOAD"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("data", Null)
m.Put("error", "Network error: " & Job.ErrorMessage)
CallSubDelayed2(Callback, EventName & "_DataLoaded", m)
Case "ADD"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("record", Null)
m.Put("error", "Network error: " & Job.ErrorMessage)
CallSubDelayed2(Callback, EventName & "_RecordAdded", m)
Case "UPDATE"
CallSubDelayed3(Callback, EventName & "_RecordUpdated", False, "Network error: " & Job.ErrorMessage)
Case "DELETE"
CallSubDelayed3(Callback, EventName & "_RecordDeleted", False, "Network error: " & Job.ErrorMessage)
Case "CREATE"
Dim m As Map
m.Initialize
m.Put("success", False)
m.Put("sheetId", "")
m.Put("error", "Network error: " & Job.ErrorMessage)
CallSubDelayed2(Callback, EventName & "_SheetCreated", m)
End Select
End If
End Sub
B4XMainPage:
Private Sub ConnectToSheet (SheetID As String)
Log($"ConnectToSheet(${SheetID})"$)
If IsLoading Then Return
IsLoading = True
SetControlsEnabled(False)
ShowStatus("Connecting...", xui.Color_ARGB(255, 66, 133, 244))
api.LoadData(SheetID)
End Sub
'--- Callbacks from GoogleSheetsAPI ---
Private Sub SheetManager_DataLoaded (m As Map)
IsLoading = False
SetControlsEnabled(True)
Dim Success As Boolean = m.GetDefault("success", False)
Dim Data As List = m.GetDefault("data", Null)
Dim ErrorMsg As String = m.GetDefault("error", "")
If Success Then
IsConnected = True
txtSheetID.Text = CurrentSheetID
B4XTable1.SetData(Data)
ShowStatus("Loaded " & Data.Size & " records", xui.Color_ARGB(255, 52, 168, 83))
Else
IsConnected = False
ShowStatus("Error: " & ErrorMsg, xui.Color_ARGB(255, 234, 67, 53))
End If
End Sub
'--- Auth callbacks ---
Private Sub Auth_AuthComplete (Success As Boolean, ErrorMessage As String)
Log($"Auth_AuthComplete(${Success}, ${ErrorMessage})"$)
If Success Then
ShowStatus("Authenticated. Ready to connect.", xui.Color_ARGB(255, 52, 168, 83))
CallSubDelayed(Me, "DelayedConnect")
Else
ShowStatus("Auth failed: " & ErrorMessage, xui.Color_ARGB(255, 234, 67, 53))
End If
End Sub
Private Sub DelayedConnect
Dim savedID As String = LoadSavedSheetID
Log(savedID)
If savedID <> "" Then
txtSheetID.Text = savedID
CurrentSheetID = savedID
ConnectToSheet(savedID)
End If
End Sub
Private Sub Auth_TokenResult (Token As String, ErrorMessage As String)
Log($"Auth_TokenResult(${Token}, ${ErrorMessage})"$)
If Token <> "" Then
Log("Setting AuthToken")
api.SetAuthToken(Token)
Else
Log("Token is empty: " & ErrorMessage)
End If
End Sub
I think I am facing a race condition.
I am not familiar with such callback calling so I am seeking help to understand the prolem.
Last edited: