Question

Edit

After moving my loading / creation code to an Async Task (see below) - I still have the initial problems that I had with my original splashscreen.

Those being that:

1) On starting the Async task in onCreate, everything is loaded but my Dialog can only be shown when onStart() is called which makes the whole process kind of pointless as there is a long pause with a blank screen, then after everything has loaded, the 'loading' dialog flashes up for a split second before disappearing.

2) I can't move object loading / creation etc to onStart because a) it will be run again even when the app is resumed after being sent to the background which I don't want to happen, and b) when when calling restoring the savedInstanceState in onCreate() I'll get a nullPointerException because i'm restoring properties of objects that won't have yet been created.

Would really appreciate if someone could advise how to get around these problems and create a simple splashscreen. Thanks!

Background

My app uses only one activity and I would like to keep it that way if possible.

I've struggled with this for over a week so really hope someone can help me out.

All I want to do is use a splashscreen with a simple 'loading' message displayed on the screen while my resources load (and objects are created etc.) There are a couple of points:

Conditions

1) The splashscreen should not have it's own activity - everything needs to be contained in a single-activity

2) The splashscreen should not use an XML layout (I have created a Splashscreen class which uses View to display a loading PNG)

3) My app is openGL ES 2.0 so the textures need to be loaded on the OpenGL Thread (creation of objects etc that don't use GL calls are OK to go on another thread if necessary).

What I've attempted so far

What I did so far was to create a dialog and display it in my onStart() method with:

Dialog.show();

then let everything load in my onSurfaceCreated method before getting rid of it with:

Dialog.dismiss();

However I needed to change this for varioius reasons so now I create my objects from a call within my onCreate() method and just let the textures load in my GL Renderer's onSurfaceCreated method.

However, this means that because the dialogue isn't displayed until after onCreate, I still get a delay (blank screen) while everything is created before the splash-screen is shown, this then stays on the screen until the textures have loaded. There are other issues with this too which can wait for another day!

So my approach is obviouly very wrong. I read every tutorial I could and every splash-screen related question I could find on SO and Gamedev.SE but I still can't find an explanation (that makes sense to me), of how this can be achieved.

I'm hope someone here can explain.

Was it helpful?

Solution

You should be able to use AsyncTask to load resources in the background and then just dismiss your splash

Here's an AsyncTask that I use to load data from a remote db. This displays a loading progress circle until the task is complete but should be easily re-purposed to display your splash

AsyncTask that runs in the background

private class SyncList extends AsyncTask<Void, ULjException, Void> {

    private static final String TAG = "SyncList";

    private final class ViewHolder {
        LinearLayout progress;
        LinearLayout list;
    }

    private ViewHolder m;

    /**
     * Setup everything
     */
    protected void onPreExecute() {
        Log.d(TAG, "Preparing ASyncTask");
        m = new ViewHolder();
        m.progress = (LinearLayout) findViewById(R.id.linlaHeaderProgress);
        m.list = (LinearLayout) findViewById(R.id.listContainer);

        m.list.setVisibility(View.INVISIBLE); //Set the ListView that contains data invisible
        m.progress.setVisibility(View.VISIBLE); //Set the loading circle visible you can sub in Dialog.show() here
    }

    /**
     * Async execution performs the loading
     */
    @Override
    protected Void doInBackground(Void... arg0) {
        try {
            Log.d(TAG, "Syncing list in background");
            dba.open(ListActivity.this);
            dba.sync();
        } catch (ULjException e) {
            publishProgress(e);
        }
        return null;
    }

    /**
     * Display exception toast on the UI thread
     */
    protected void onProgressUpdate(ULjException... values) {
        Log.e(TAG, values[0].getMessage());
        Toast.makeText(ListActivity.this, "Sync failed", Toast.LENGTH_LONG).show();
    }

    /**
     * Finish up
     */
    protected void onPostExecute(Void result) {
        Log.d(TAG, "ASyncTask completed, cleaning up and posting data");
        fillData();
        m.list.setVisibility(View.VISIBLE); //Show the list with data in it
        m.progress.setVisibility(View.INVISIBLE); //Hide the loading circle sub in Dialog.dismiss()
    }
}

Calling the Task

protected void onStart() {
    super.onStart();
    // Init the dba
    dba = DBAccessor.getInstance();
    new SyncList().execute();
}

It should be noted that the AsyncTask is an inner class of the Activity its related to here

Edit
onCreate Method

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_layout);

    Dialog.show();
    //This launches a new thread meaning execution will continue PAST this call
    //to onStart and your loading will be done concurrently
    //Make sure to not try to access anything that you're waiting to be loaded in onStart or onResume let your game start from onPostExectue
    new AsyncTask.execute();
}

doInBackground

protected Void doInBackground(Void... arg0) {
    Load all resources here
}

onPostExecute

protected void onPostExecute(Void result) {
    Dialog.dismiss();
    Call a method that starts your game logic using your newly loaded resources
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top