Overview
My splash screen starts by display a 'loading' dialogue and then kicks off an asyncTask (The loading dialogue is derived from the standard Android View class)
Within the doInBackground method of the asyncTask, all of my quads / sprite objects are created and other values set etc.
When the code gets to onSurfaceCreated, it loads all of the textures and runs the game.
The texture loading happens in onSurfaceCreated because it has to be done on the GL Thread.
Now, on a nice fast tablet, it all works great and it's all very stable. However, when I run it on an old handset, it (intermittently) crashes all over the place with nullpointerexceptions.
Reason
What's happening is on the slower device, the asyncTask is running and (due to the asynchronous nature of it), continues to run in the background while the main code moves on to the onSurfaceCreate method of the GLRenderer, there it attempts to apply textures to objects that don't yet exist because the asyncTask is still doing it's business.
How best to proceed?
What are some methods I can implement that would allow me to guarantee that the async has done it's stuff before attempting to affect any of the objects that it creates?
Is there a way to 'halt' the GLThread until the asyncTask has finished? I've been told in the past to use a separate thread or an async for loading resources, but I'm confused as to how to handle it correctly and keep everything sync'd between it and the GL thread (if "sync'd" is the correct term in this context).
Any help would be appreciated.
Code example
Showing onCreate and doInBackground from Activity Class
@Override
protected void onCreate(Bundle savedInstanceState) {
//Request full screen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
super.onCreate(savedInstanceState);
//Create a displayMetrics object to get pixel width and height
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
width = metrics.widthPixels;
height = metrics.heightPixels;
//Create splash-screen object and pass in scaled width and height
splash = new SplashScreen(MainActivity.this, width, height);
//Create dialog that will show splash-screen
loading_dialog = new Dialog(MainActivity.this,android.R.style.Theme_Black_NoTitleBar_Fullscreen);
//Create and set View
myView = new MyGLSurfaceView(MainActivity.this);
//Create a copy of the Bundle
if (savedInstanceState != null){
newBundle = new Bundle(savedInstanceState);
}
//Create splash object
goSplash = new DisplaySplash(newBundle);
goSplash.execute(); //Start asyncTask
setContentView(layout);
}
And....
@Override
protected Void doInBackground(Void... params) {
createObjects();
initialise();
return null;
}
Showing onSurfaceCreated from GLRenderer Class
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//Eek! Running before AsyncTask has finished on slower devices! :(
res.loadResources();
res.setTextures();
res.RecycleBitmaps();
}