Android - Ending activity from within rendering thread
Good afternoon.
I am unfamiliar with the activity life cycle in android and have been reading up as best as possible but I cannot figure how to solve the following in a nice manner.
I have an activity with a GLSurfaceView to draw various things on the screen. In the renderering thread for this GLSurfaceView I perform all the rendering as well as the actual update logic (I will seperate this out eventually).
The trouble I am having is from one of the "screens" drawn within the renderer I wish to end the Ac开发者_Python百科tivity and have it call the various lifecycle methods.
Normally I might do this with System.exit(0); however ending the activity in this way does not seem to call the OnStop(); OnDestroy(); methods.
This might just be me being silly and not seeing an easy way of doing this but is there a way to access the Activity and call activity.finish(); without having to pass the reference to it all the way down?
This is probably less of an android question and more a general java problem? Sorry I am a little rusty at both. Maybe if someone could explain roughly how they handle an issue like this in their app.
You do need to obey thread safety rules and not call activity.finish() directly from your render thread. The best way to handle this is to post a runnable back onto the event queue for the UI Thread. And let that Runnable call activity.finish().
You don't have to pass the activity down to the area where you plan on stopping the activity. Here is what I'd do. Pass the activity to the class you instantiate in onCreate(). Something like:
public void onCreate( ... ) {
MyRenderer renderer = new MyRenderer( glSurface, this );
}
Then inside MyRenderer I'd do something like:
public void someMethodInRenderer() {
if( stop ) {
stop();
}
}
public void stop() {
Handler handler = new Handler();
handler.post( new Runnable() {
public void run() {
activity.finish();
}
} );
}
Notice the Handler used to post back to the UI thread. That makes it safe to call activity.finish(). I couldn't find any specific information in the docs stating it's safe or not safe to call finish() from another thread so to be on the safe side post it back.
Things to keep in mind. If someMethodInRenderer() is deep within the bowels in your program then you don't have to have access directly to the activity instance. You just need a reference so something that eventually calls to the activity to finish. So maybe there is a reference to another part of the system you are passing down to that method where you can add the stop(). So stop() and someMethodInRenderer() could be in the same class, or in different classes. That's a choice you'll have to make. Eventually this is an architecture issue you have to decide.
If the renderer thread is inside the Activity, you can use ActivityClassName.this.finish();
To address an issue I ran into:
If you finish your activity (including from another thread) via activity.finish()
it is important that the render thread's onDraw()
method is not blocked (happened to me due to my implementation of double buffer rendering).
In that case, only the onPause()
method in the activity class got called. The methods onStop()
and onDestroy()
weren't called even though the app finished with a short delay.
Hope this helps anybody facing the same problem.
Edit: The reason was, that in my activity.onPause()
method I called glSurfaceView.onPause()
while the render thread's onDraw()
was blocked.
精彩评论