Mr. Pivirotto
Mr. Pivirotto

Reputation: 281

Timer not stopping after activity has been closed and restarted

I have a runnable timer that update a textview every second, when the activity is onStop (or called into the background) the timer continues to run. The issue i am having is that when i re-launch the activity it starts the same timer again, so the numbers are going up twice as fast as they should. I have it coded so that it will kill both timers before it restarts them but i believe that when the activity is started again the timers are not being killed. Here is an example of my code :

    t.cancel();
    cd.cancel();
   t = new Timer();
    t.schedule(new TimerTask() {

        @Override
        public void run() {
            runOnUiThread(new Runnable() {

                public void run() {

That is only a small part but it should kill the timer (t.cancel();) then start a new one, this only happens when the activity is stopped and then restarted. please help this issue is driving me absolutely insane.

=========================================================

For the brave souls willing to read alot, here is my entire activity that i am having the issue with:

    public class PayTracker extends Activity {
    private static double Reserve;
    private static int Reserve1;
    public static double money;
    public static double counter;
    private static int go;
    private static int countdown;
    public static int convert;
    public static double HW;
    public static double OTW;
    public static double HPD;
    public static double DPPS;
    public Timer t = new Timer();
    public Timer cd = new Timer();
    public static String mcountdown = "Time till overtime";
    public static String mmoney = "total cash";
    public static String mcounter = "ticks";
    public static String mReserve = "building total";
    public static String mReserve1 = "building total 2";
    public static String mHW;
    public static String mOTW;
    public static String mHPD;
    public static String mDPPS;
    public static String mgo;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pay_tracker);
        getActionBar().setDisplayHomeAsUpEnabled(true);
     // Receive messages from options page
       double pHW, pOTW, pHPD;
        Intent intent = getIntent();
        pHW = intent.getDoubleExtra(Options.MESSAGE_HW, 0);
        pOTW = intent.getDoubleExtra(Options.MESSAGE_OTW, 0);
        pHPD = intent.getDoubleExtra(Options.MESSAGE_HPD, 0);
        if(pHW != 0){
            HW = pHW;
            OTW = pOTW;
            HPD = pHPD;
        }
     // Color buttons
        Button buttonc = (Button) findViewById(R.id.clockin);
        buttonc.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
        Button buttond = (Button) findViewById(R.id.clockout);
        buttond.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);

//      go = 0;
        // Calculate pay per second
        final double PPS = (HW/3600);
        DPPS = (PPS/50);
        final double OTPPS = (OTW/3600);
        final double DOTPPS = (OTPPS/50);
        final double HPDPS = (HPD*3600);
        final double DHPDPS = (HPDPS*50);
        // Display

        final TextView t1 = (TextView) findViewById(R.id.yourpay);
        t1.setTextColor(Color.parseColor("#008000"));
        final TextView t2 = (TextView) this.findViewById(R.id.payper);
        final String result2 = String.format("%.8f", OTPPS);
        final String result = String.format("%.8f", PPS);

       // if(go != 1){
       //   go = 1;
       // if(go == 1){
        t.cancel();
        cd.cancel();
       // go = 0;
       // }
       // if(go == 0){
       //   go = 1;
       t = new Timer();
        t.schedule(new TimerTask() {

            @Override
            public void run() {
                runOnUiThread(new Runnable() {

                    public void run() {
                        if(DHPDPS==0){
                            money = (DPPS+Reserve);
                            Reserve = (money);
                            String end = String.format("%1f", money);
                            t1.setText("$" + end);
                        }else if(counter > DHPDPS && DOTPPS != 0 && DHPDPS != 0){
                            money = (DOTPPS+Reserve);
                            Reserve = (money);
                            String end = String.format("%1f", money);
                            t1.setText("$" + end);
                        } else{

                            money = (DPPS+Reserve);
                            Reserve = (money);
                            String end = String.format("%1f", money);
                            t1.setText("$" + end);
                        }
                        counter++;
                        //if(counter == 3000)
                        //   t.cancel();

                        // Display pay per second
                        if(counter <= DHPDPS || DHPDPS == 0){
                        t2.setText("Your pay per second is: $"+result);
                        }else{
                            t2.setText("Your pay per second is: $"+result2);
                        }
                    }
                }); 
            }
        }, 20, 20);

     // Make countdown to overtime display

        final Intent intent1 = new Intent(this, PayTracker.class);
     // Create the notification
        final Notification notification = new Notification(R.drawable.ic_launcher, "Click here to check your pay!", System.currentTimeMillis());
        // Create an Intent for the notification to launch
        // Create a PendingIntent for the associated Intent
        final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent1, 0);
        cd = new Timer();
        final TextView count = (TextView) findViewById(R.id.countdown);
        convert = (int)HPDPS;
        cd.schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    public void run(){
                        countdown = (convert - Reserve1);
                        int hours = (countdown/3600);
                        if(OTPPS != 0 && HPDPS != 0){
                                count.setText("Seconds Remaining to Overtime: " + countdown + "\nAbout " + hours + " Hours");
                                Reserve1++;
                            }

                        // Set the notification's details
                        final String end = String.format("%.6f", money);
                        notification.setLatestEventInfo(getApplicationContext(), "Your Current Pay:", "$"+end, pendingIntent);
                        // Submit the notification to the system
                        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(0, notification);
                    }
                });
            }

        }, 1000, 1000);
       // }
       // }


         final Button b = (Button) findViewById(R.id.clockout);
         b.setOnClickListener(new OnClickListener() {
             public void onClick(View v) {
                if(go == 1)
                    go = 0;
                 if (t != null){
                     t.cancel();
                     cd.cancel();
                 }
                 }
         });

    }

    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Always call the superclass so it can restore the view hierarchy
        super.onRestoreInstanceState(savedInstanceState);
            // Restore value of members from saved state
            countdown = savedInstanceState.getInt(mcountdown);
            Reserve = savedInstanceState.getInt(mReserve);
            money = savedInstanceState.getInt(mmoney);
            counter = savedInstanceState.getInt(mcounter);
            Reserve1 = savedInstanceState.getInt(mReserve1);
            HW = savedInstanceState.getInt(mHW);
            OTW = savedInstanceState.getInt(mOTW);
            HPD = savedInstanceState.getInt(mHPD);
            DPPS = savedInstanceState.getInt(mDPPS);
            go = savedInstanceState.getInt(mgo);
    }

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


    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_pay_tracker, menu);
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void sendMessage(View view) {
        // Calculate pay per second
        final double PPS = (HW/3600);
        DPPS = (PPS/50);
        final double OTPPS = (OTW/3600);
        final double DOTPPS = (OTPPS/50);
        final double HPDPS = (HPD*3600);
        final double DHPDPS = (HPDPS*50);
        // Display

        final TextView t1 = (TextView) findViewById(R.id.yourpay);
        t1.setTextColor(Color.parseColor("#008000"));
        final TextView t2 = (TextView) this.findViewById(R.id.payper);
        final String result2 = String.format("%.8f", OTPPS);
        final String result = String.format("%.8f", PPS);

        //if(go != 1){
        //  go = 1;
            t.cancel();
            cd.cancel();
       t = new Timer();
        t.schedule(new TimerTask() {

            @Override
            public void run() {
                runOnUiThread(new Runnable() {

                    public void run() {
                        if(DHPDPS==0){
                            money = (DPPS+Reserve);
                            Reserve = (money);
                            String end = String.format("%1f", money);
                            t1.setText("$" + end);
                        }else if(counter > DHPDPS && DOTPPS != 0 && DHPDPS != 0){
                            money = (DOTPPS+Reserve);
                            Reserve = (money);
                            String end = String.format("%1f", money);
                            t1.setText("$" + end);
                        } else{

                            money = (DPPS+Reserve);
                            Reserve = (money);
                            String end = String.format("%1f", money);
                            t1.setText("$" + end);
                        }
                        counter++;
                        if(counter == 3000)
                           t.cancel();

                        // Display pay per second
                        if(counter <= DHPDPS || DHPDPS == 0){
                        t2.setText("Your pay per second is: $"+result);
                        }else{
                            t2.setText("Your pay per second is: $"+result2);
                        }
                    }
                }); 
            }
        }, 20, 20);

     // Make countdown to overtime display

        final Intent intent1 = new Intent(this, PayTracker.class);
     // Create the notification
        final Notification notification = new Notification(R.drawable.ic_launcher, "Click here to check your pay!", System.currentTimeMillis());
        // Create an Intent for the notification to launch
        // Create a PendingIntent for the associated Intent
        final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent1, 0);
        cd = new Timer();
        final TextView count = (TextView) findViewById(R.id.countdown);
        convert = (int)HPDPS;
        cd.schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    public void run(){
                        countdown = (convert - Reserve1);
                        int hours = (countdown/3600);
                        if(OTPPS != 0 && HPDPS != 0){
                                count.setText("Seconds Remaining to Overtime: " + countdown + "\nAbout " + hours + " Hours");
                                Reserve1++;
                            }

                        // Set the notification's details
                        final String end = String.format("%.6f", money);
                        notification.setLatestEventInfo(getApplicationContext(), "Your Current Pay:", "$"+end, pendingIntent);
                        // Submit the notification to the system
                        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(0, notification);
                    }
                });
            }

        }, 1000, 1000);

        //}   
    }



    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save the user's current game state
        savedInstanceState.putInt(mcountdown, countdown);
        savedInstanceState.putDouble(mReserve, Reserve);
        savedInstanceState.putDouble(mmoney, money);
        savedInstanceState.putDouble(mcounter, counter);
        savedInstanceState.putDouble(mReserve1, Reserve1);
        savedInstanceState.putDouble(mHW, HW);
        savedInstanceState.putDouble(mOTW, OTW);
        savedInstanceState.putDouble(mHPD, HPD);
        savedInstanceState.putDouble(mDPPS, DPPS);
        savedInstanceState.putInt(mgo, go);

        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
    }

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

        if(t != null)
            t.cancel();
        if(cd != null)
            cd.cancel();   
    }

}

Upvotes: 0

Views: 1056

Answers (1)

Frank Sposaro
Frank Sposaro

Reputation: 8531

This is one way to get around that.

static Timer mTimer = null;

onCreate() {
    if (mTimer == null)
        mTimer = new Timer();
    } else {
        // You shouldn't have to do nothing because your timer should be running
    }
}

Note that there are several issues in general here. The static is basically saying just to create one instance of that object. As a side effect it also tries to reclaim the same memory address. Either way, once your app is in the background it can be cleaned up by the system at any time so your not guaranteed to get your Timer back. There are a bunch of other ways to get around that, but that is out of scope for this question.

Upvotes: 1

Related Questions