Android Example CallSubDelayed - Avoid Black Screen

This has plagued me for months... (drove me nuts!)

I would try to insert a record in a table within an activity (using CallSubDelayed2) - then start another activity and presented with a Black Screen...

The solution (to date) is to call the CallSubDelayed2 within the new activity within a timer... ( as Erel stated in a found post).


B4X:
Sub timer_tick
  Dim tt,elp As Long
  tt = DateTime.Now

  elp = tt - tck
  Activity.Title = "Location: "&DefCM.CurrLoc
  btnDone.text = "DONE"&CRLF&DefCM.ShowSeconds(elp) '   DateTime.Time(DateTime.Now)
 
   If  MakeLRec Then
      LogCM.SetCurrLogStat(act_stat)
      logact = LogCM.CurrLogName
      CallSubDelayed2( LogServmod,"MakeLogRecord",act_stat)  ' this will not cause the call to block and show a Black Screen on current activity
      MakeLRec = False
      Log(" Made act Log Record")
      Label3.Text = logact&" ~ "&Label3.Text
   End If

End Sub

https://www.b4x.com/android/forum/threads/callsubplus-callsub-with-explicit-delay.60877/

Trying to update (or insert) a record with CallSubDelayed2 outside this timer would (often) cause the screen to go blank (black) since it would hold up the main thread (took too long to process) with no way to recover... Refer to above link for reference...
 

Harris

Expert
Licensed User
Longtime User
Note that there is another option here, which is to use SQL.ExecNonQueryBatch to process the SQL commands in the background.
I am only inserting one record into a table with this call.
I use the same call in many other places, but not when starting an activity.

Very good advise however, seems very useful for non-blocking.

I shall try it in this instance to see how it behaves.

Thanks
 

Harris

Expert
Licensed User
Longtime User
Another way to cause a black screen.... Try and show a MsgBox from within your code module....
It was buried in the else clause and would only appear when no one was looking, resulting in the wonderful black screen.

Would (or should) this raise an error in the logs - like other warnings?
I know you have already advised us elsewhere.


B4X:
Sub Getpkstats(val As Long) As Int  ' in a code module...

    Dim c As Cursor
    Dim ID As Int

    c = DefCM.SQL3.ExecQuery2("Select LogID from LogStats WHERE LogDate = ?",Array As String(val))

    If c.RowCount > 0 Then
       c.Position = 0
       ID = c.GetInt("LogID")
    Else
     '  Msgbox("Could Not Find Status Record","Error")
       ID = 0
      
    End If

    c.Close
    Return ID

End Sub
 

Harris

Expert
Licensed User
Longtime User
Note that there is another option here, which is to use SQL.ExecNonQueryBatch to process the SQL commands in the background.

My Main activity module calls the service module that invokes the ExecNonQueryBatch routine. This works fine when in Main.
However, if I use CallSubDelayed(Main,"method") to call the function of the Main mod from another activity module (which calls the service module in turn), I get a black screen (eventually).

So, I copy the subs from Main and paste them into current activity. Every thing seems fine...

Perhaps both (duplicate subs) need to be in the service module?

Other question: Can CallSubDeleyed... return a value?

Thanks
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You should move all the relevant code to the service. An activity shouldn't call another activity unless it wants to start it.

Other question: Can CallSubDelayed... return a value?
No. This is technically impossible as the sub is not called immediately.

CallSub can return a result.
 

Harris

Expert
Licensed User
Longtime User
Ok, I found the answer, AGAIN. (my bad).

Moved all to an existing service...

As I have learned before, but quickly forgotten, is to use the event raised from the "myevent_NonQueryComplete(Success As Boolean)" to (in this case) start the activity that uses tables I built in the callsubdelayed... Otherwise, the tables might not be built in time and the called activity will "black screen". with no error message in the debug to determine what the heck went wrong, since (I suppose), it was still in the process of building the tables...

This is the essence of event driven programming.. Do what you need to do NEXT, AFTER the prior proc has told you that it was finished (succeeded), in the event raised.
I my case was to Start the Activity (StartActivity(Inspection)) ...

Freak, I hope I have finally learned this lesson, and my diminished gray matter will retain it...
Perhaps it might be helpful to drive this point home in your response (ie. use event raised to start next process - or short example link), since it might not be obvious to procedural programmers, like my dumb ass.

Thanks
 
Top