In Android game (written in Java) I have an activity that's calling service and service calls a manager that checks certain values. Activity code looks something like this:
public void performACheck() {
service.doYourThing();
decideIfGameIsLostOrWon();
}
Sometimes, that deep code from withing Manager inside of "service" needs to "resurface" and ask user (via AlertDialog) to make a decision (choosing a value) that might prevent him from losing the game. Communication between "deep code" and Activity is made using observer pattern. Obviously method "decideIfGameIsLostOrWon()" shouldn't be called before player makes a choice, but in case no AlertDialog is shown, method "decideIfGameIsLostOrWon()" should be executed as normal.
The problem is, whatever I tried so far (Handlers, CountDownLatches) - method "decideIfGameIsLostOrWon()" is always executed before AlertDialog is presented. As if Activity class gets notified about PropertyChange (observer) in the very end or by some default Android always handles showing AlertDialog after entire method that's calling it has been executed.
I'm so desperate that i'm considering freezing the main thread after "service.doYourThing();" is called to make sure I stop rest of the method from executing before any pending AlertDialog is shown and result properly handled...
Any idea what's going on and how to solve this?
Freezing the main thread wouldn't help. Dialog boxes don't appear until the app redraws itself. The app doesn't redraw itself until the main thread returns to the Looper. That means that there is no way to execute something that waits for the result of a dialog box on the main thread. You need to use asynchronous code of some sort.
The correct way of doing this- set a timer. If the timer expires, treat it as the dialog box timing out and call decideIfGameIsWLostOrWon. Display your dialog, and use standard event processing on the options. When they choose an option, call decideIfGameIsLostOrWon(). If you decide not to show a dialog box for some reason, you can either wait for the timeout, or you can set some value that tells you that you didn't show a dialog and call decideIfGameIsLostOrWon immediately.
As an aside, if you're using kotlin rewriting this as a coroutine is probably the best thing to do.