abuybuy
abuybuy

Reputation: 819

Didn't update UI when pause and resume thread

i am doing an android project right now. i have problem with thread in it. i want to pause thread when home button pressed and resume it when going back to the app.

this is my code:

Handler handler = new Handler() 
{
    @Override
    public void handleMessage(Message msg) 
    {
        int tempWaktu = (Integer) msg.obj;

        if(!status){
            if(tempWaktu < 10 ) textSec.setText("0"+tempWaktu);
            else textSec.setText(""+tempWaktu);
        }

        if(tempWaktu==0){
            stopYourActivity();
        }
    }
}; //handler

@Override
public void onStart() 
{
    super.onStart();

    timer = new Thread(new Runnable() {
        public void run() {
        try 
        {
            while(jalan){
                if(running){
                    Thread.sleep(1000);
                    waktu--;
                    Message msg = handler.obtainMessage(1, waktu);
                    handler.sendMessage(msg);
                    if(waktu==0){
                        running = false;
                    }
                }
            }
        } 
        catch (Throwable t){

        }
    }//run
    });//background
    timer.start();
}//onStart


@Override
public void onPause(){
    synchronized (timer) {
        try {
            timer.wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    pause = true;
}

@Override
public void onResume(){
    super.onResume();
    if(pause){
        synchronized (timer) {
            timer.notify(); textSec.postInvalidate();
            pause = false;
        } 
    }
}

when i press home button, the thread won't stop and when i back to the app, the UI is freeze. i don't understand why.

what i need is when i press the home button the thread paused and when i back the thread running and the UI is not freeze.

i appreciate any code that you write to help me. thank you very much.


UPDATE

i have put timer.wait() inside run() like this:

@Override
public void onStart() 
{
    super.onStart();

    if(!pause){
        timer = new Thread(new Runnable() {
            public void run() {
            try 
            {
                while(jalan){
                    if(running){
                        Thread.sleep(1000);
                        waktu--;
                        Message msg = handler.obtainMessage(1, waktu);
                        handler.sendMessage(msg);
                        Log.v("Timer Thread", "Thread Berjalan "+waktu);
                        if(waktu==0){
                            Log.v("Thread Timer", "Waktu Berhenti");
                            running = false;
                        }
                        if(pause){
                            synchronized (timer) {
                                timer.wait();
                            }
                        }
                    }
                }
            } 
            catch (Throwable t){    
            }
        }//run
        });//background
        timer.start();
    }

}//onStart

and timer.notify() is in onResume() just like above and when i pressed the home it comes to Force Close. Here's the log says:

07-19 10:27:41.173: E/AndroidRuntime(2280): FATAL EXCEPTION: main
07-19 10:27:41.173: E/AndroidRuntime(2280): android.app.SuperNotCalledException: Activity {com.konsep.baby.scratch/com.konsep.baby.scratch.BabyScratchChallenge} did not call through to super.onPause()
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.Activity.performPause(Activity.java:3854)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1191)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2341)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2311)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2291)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.access$1700(ActivityThread.java:117)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:938)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.os.Looper.loop(Looper.java:123)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.main(ActivityThread.java:3683)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at java.lang.reflect.Method.invokeNative(Native Method)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at java.lang.reflect.Method.invoke(Method.java:507)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at dalvik.system.NativeStart.main(Native Method)

what is wrong with my code?

Upvotes: 0

Views: 3624

Answers (2)

devunwired
devunwired

Reputation: 63293

The first problem is how the lifecycle of an Activity actually works. When you go to the Home screen, your current Activity goes all the way through to the stopped state (i.e. onStop() gets called). Therefore, when you return to the application, you will receive onStart() then onResume(). Now, let's examine what happens in your code based on that information:

  1. On first launch, a new Thread is created in onStart() and started. onResume() does nothing due to the boolean flag.
  2. Pressing the HOME button, onPause() is called, calling wait() on this Thread
  3. Return to the application, onStart() is called and now timer points to a new Thread, leaving your old Thread dangling.
  4. onResume() is called and notify() is sent to the new Thread instance.

So the issue here is that the Thread you wait() and the thread you notify() are not the same object.

The second issue is what wait() actually does. From the Java docs (emphasis added):

Causes the calling thread to wait until another thread calls the notify() or notifyAll() method of this object. This method can only be invoked by a thread which owns this object's monitor; see notify() on how a thread can become the owner of a monitor.

Calling wait() on a Thread doesn't block that created Thread, it blocks the thread that called the method, which in this case in the main thread. So you've written an application that successfully blocks the main thread during pause and has no way to unlock it, hence the freeze.

If you want to use wait() and notify() to pause your background thread, you need to make sure that wait() is called from within the background thread (i.e. inside it's run() block)

Upvotes: 1

Clover
Clover

Reputation: 46

Google's training page has already explained.Here

When your app is paused,it "Stop animations or other ongoing actions that could consume CPU."

Upvotes: 0

Related Questions