JFFF
JFFF

Reputation: 989

Android thread confusion

I have written a function to create a splash screen with a 5 second timeout for my app.

The code works fine, but when the timeout reaches zero and I want to redirect to my main activity, the app crashes with the following error:

Only the original thread that created a view hierarchy can touch its views.

So I looked around a bit and someone suggested nesting this inside my function. It seems like a good Idea, but now methods like sleep / stop won't work.

My code is below, I can provide more / explain more in details if it isn't clear enough just let me know. Thanks for the help.

        @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        showSplashScreen();

    }

    protected boolean _active = true;
    protected int _splashTime = 5000;  // Splash screen is 5 seconds

    public void showSplashScreen() {

        setContentView(R.layout.splash_layout);

//      Thread splashThread = new Thread() {

         runOnUiThread(new Runnable() {

             @Override
             public void run() {
                 try {
                     int waited = 0;
                     while (_active && (waited < _splashTime)) {
                         Thread.sleep(100);
                         if (_active) {
                             waited += 100;
                         }
                     }
                 } catch (InterruptedException e) {
                     // do nothing
                 } finally {
                     showApplication();
                 }
             }
         });
    }

Upvotes: 1

Views: 231

Answers (5)

Knickedi
Knickedi

Reputation: 8787

This will perform sleep on the UI thread. That's never a good idea.

Why not something like this?

new Handler().postDelayed(new Runnable() {
    public void run() {
        // start application ...
    }
}, _splashTime);

But this answer has a good point. Displaying a splash screen for 5 seconds can be very annoying.

Upvotes: 2

ggurov
ggurov

Reputation: 1526

I suggest you to make new activity for your spalsh screen, show it in a regular way (with startActivityForResult) and place in it such code (in it, not in your main activity):

new Handler().postDelayed( new Runnable()
  {
  public void run()
    { finish(); }
  }, 5000 );

Also you can handle in this new activity click events for giving opportunity to user to close it faster, tapping on it.

Upvotes: 0

pzulw
pzulw

Reputation: 1746

Use a Handler to post an event to the UI thread that will remove the splash.

Code should be something like...

   splash.show()
   new Handler().postDelayed(
      new Runnable() {
          void run() {
              splash.remove();
          },
      delayTime);

Upvotes: 0

Kurtis Nusbaum
Kurtis Nusbaum

Reputation: 30825

Probably not what you want to hear, but you should never put a splash screen on your mobile app. With the exception of games, when people use a mobile app they want to get in, do what ever it is they need to do, and get out. If you make that process take longer, people are just going to get frustrated with you app. You should probably reconsider just not using a splash screen.

Upvotes: 7

Mike Marshall
Mike Marshall

Reputation: 7850

I believe you want AsyncTask for this. The method called on completion of the task will be called on your UI thread, making modifying UI elements much easier.

Upvotes: 2

Related Questions