3

I'm currently using below structure in my splash screen activities in order to show it for specified time period:

    new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
            startMainActivity();
       }
    }, SPLASH_DISPLAY_LENGHT);

However I'm just creating an app which loads some information on its splash screen from network using an AsyncTask like this:

startUpAsyncTask = new StartUpAsyncTask(this);
startUpAsyncTask.execute();

Now I want to implement Handler such that:

  1. If something failed during network load, it stops handler to move to MainActivity.
  2. If network loading last longer than SPLASH_DISPLAY_LENGHT activity waits till network load completes in StartUpAsyncTask and then move to next activity.
  3. If network StartUpAsyncTask finished very soon, splash screen is shown for at least SPLASH_DISPLAY_LENGHT time length.

My problem is how to synchronize this AsyncTask and Handler to achieve such constraints.

VSB
  • 9,825
  • 16
  • 72
  • 145

4 Answers4

4

You may register a BroadcastReceiver registered with a LocalBroadcastManager in your splash screen which will receive a successful message from your AsyncTask and set a flag. Another BroadcastReceiver will be registered in your handler in case the flag is not already set when SPLASH_DISPLAY_LENGHT is already past and will startMainActivity() when the broadcast is received from your AsyncTask; else if the flag is already set when the SPLASH_DISPLAY_LENGHT is completed in your handler, it will directly startMainActivity().

In your SplashActivity:

private class SplashActivity extends Activity {
    public static final String ACTION_DATA_LOADING_COMPLETE = "com.example.myapp.ACTION_DATA_LOADING_COMPLETE";

    private LocalBroadcastManager localBroadcastManager;

    private boolean dataLoadingComplete = false;

    @Override
    private void onCreate(Bundle savedInstanceState) {
        ...

        localBroadcastManager = LocalBroadcastManager.getInstance(this);

        localBroadcastManager .registerBroadcastReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                dataLoadingComplete = true;
            }
        }, new IntentFilter(ACTION_DATA_LOADING_COMPLETE));

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                localBroadcastManager.registerBroadcastReceiver(new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        startMainActivity();
                    }
                }, new IntentFilter(ACTION_DATA_LOADING_COMPLETE));

                if (dataLoadingComplete)
                    localBroadcastManager.sendBroadcast(new Intent(ACTION_DATA_LOADING_COMPLETE));
            }
        }, SPLASH_DISPLAY_LENGHT);
    }
}

In your AsyncTask:

@Override
onPostExecute(...) {
    super.onPostExecute(...)

    ...

    LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(SplashActivity.ACTION_DATA_LOADING_COMPLETE));
}
Kamran Ahmed
  • 7,661
  • 4
  • 30
  • 55
4
package com.example;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.AsyncTask;

public class SplashActivity extends Activity{

    private Timer timer;
    private boolean isTaskRunning = false;
    private boolean isTimerFinished = false;
    private long SPLASH_DURATION = 2*1000;

    protected void onCreate(android.os.Bundle savedInstanceState) {
        setContentView(R.layout.badgeview);

        new MyTask().execute();

        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                isTimerFinished = true;
               if(!isTaskRunning){
                   //startNextActivity;
               }

            }
        }, SPLASH_DURATION);

    }

    class MyTask extends AsyncTask<Void, Void, Void>{
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            isTaskRunning = true;
        }
        @Override
        protected Void doInBackground(Void... params) {
            //do whatever you require from network
            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            isTaskRunning = false;
            if(!isTimerFinished){
                timer.cancel();
            }
            //startNextActivity
        }
    }
}
ByteHamster
  • 4,884
  • 9
  • 38
  • 53
Ashish Agrawal
  • 1,977
  • 2
  • 18
  • 32
1
private static final long SPLASH_DURATION = 2*1000;
private long mStartTimestamp;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout);

    mStartTimestamp = System.currentTimeMillis();
    new MyTask().execute();
}

class MyTask extends AsyncTask<Void, Void, Boolean>{

    @Override
    protected Boolean doInBackground(Void... params) {
        // your logic here
        return true;
    }

    @Override
    protected void onPostExecute(Boolean success) {
        super.onPostExecute(success);
        // check your result here
        if(success){
            long timeStop = System.currentTimeMillis();
            long delta = timeStop - mStartTimestamp;
            if (delta >= SPLASH_DURATION) {
                startMainActivity();
            } else {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        startMainActivity();
                    }
                }, SPLASH_DURATION - delta);
            }
        } else {
            // handle the error
        }
    }
}
DmitryArc
  • 4,757
  • 2
  • 37
  • 42
0

put a condition in handler like this

new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
            if(isTaskSuccessfull)
            startMainActivity();
            else
                isHandlerTimeout = true;
       }
    },

in Asyn's OnPost() method first change the value of flag(isTaskSuccessfull) to true from asyn task when task is completed successfully next check whether isHandlerTimeout is true if so call the method startMainActivity() from asyn's onPost().