简体   繁体   中英

Stop and Start a thread Android

I am trying to have an EditText that is continuously updated with the elapsed time. This is handled by a thread which calls a method to calculate the elapsed time and set the EditText text to the elapsed time. The thread sleeps every second. The thread starts when the user presses "Start" and should stop when the user presses "Stop". When the user presses "Start" again, the thread should start over again at 0 (because the start time is reset). Here is the code:

public class MainActivity extends AppCompatActivity {

    public Date start;
    public Date end;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button startButton = (Button) findViewById(R.id.startButton);
        Button endButton = (Button) findViewById(R.id.stopButton);
        final EditText dateEditText = (EditText) findViewById(R.id.dateEditText) ;
        final EditText hoursEditText = (EditText) findViewById(R.id.hoursEditText); //the one I want to update

        final DateFormat df = new SimpleDateFormat("MM/dd/yy");

        final Thread t = new Thread() {

            @Override
            public void run() {
                try {
                    while (!isInterrupted()) {
                        Thread.sleep(1000);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                setTimeElapsed(hoursEditText);
                            }
                        });

                    }
                } catch (InterruptedException e) {

                }
            }
        };

        startButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                start = new Date();
                dateEditText.setText(df.format(start));
                hoursEditText.setText("");
                t.start();
            }
        });


        endButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                t.interrupt();
                if (start == null) {
                    //write error message
                }
                else {
                    setTimeElapsed(hoursEditText);
                    start = null;
                }
            }
        });



    }

    public void setTimeElapsed(EditText hoursEditText)
    {
        end = new Date();
        long diff = end.getTime() - start.getTime();
        String diffFormatted = String.format("%02d:%02d:%02d",
                TimeUnit.MILLISECONDS.toHours(diff),
                TimeUnit.MILLISECONDS.toMinutes(diff)
                        - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(diff)),
                TimeUnit.MILLISECONDS.toSeconds(diff)
                        - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(diff)));

        hoursEditText.setText(diffFormatted);
    }
}

As you can see, the problem is that when I press "Stop" and then press "Start" again, the app throws an error because the thread was already running. If I don't have the interrupt statement, then the app crashes because it thinks start is null. I would just like to stop the thread when the stop button is pressed, and start counting from 0 when the start pressed.

EDIT:

One way I've gotten around this is by having a method that creates a new thread and calling that method in my startButton listener

public void startThread(final EditText hoursEditText){
        t = new Thread() {

            @Override
            public void run() {
                try {
                    while (!isInterrupted()) {
                        Thread.sleep(1000);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                setTimeElapsed(hoursEditText);
                            }
                        });

                    }
                } catch (InterruptedException e) {

                }
            }
        };

        t.start();
    }

But this creates a new thread every time someone presses start. This is not a good.

You can use handler

 Handler handler = new Handler();
 final Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            setTimeElapsed(hoursEditText);
            handler.postDelayed(this, 100);
        }
    });

// On end button click you can remove handler callback

endButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if(handler != null)
                handler.removeCallbacksAndMessages(null);
            }
        });

Complete code

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    public Date start;
    public Date end;
    Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button startButton = (Button) findViewById(R.id.startButton);
        Button endButton = (Button) findViewById(R.id.stopButton);
        final EditText dateEditText = (EditText) findViewById(R.id.dateEditText);
        final EditText hoursEditText = (EditText) findViewById(R.id.hoursEditText); //the one I want to update

        final DateFormat df = new SimpleDateFormat("MM/dd/yy");

        final Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                setTimeElapsed(hoursEditText);
                handler.postDelayed(this, 100);
            }
        });

        startButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                start = new Date();
                dateEditText.setText(df.format(start));
                hoursEditText.setText("");
                handler.post(thread);
            }
        });


        endButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if(handler != null)
                handler.removeCallbacksAndMessages(null);
            }
        });


    }

    public void setTimeElapsed(EditText hoursEditText) {
        end = new Date();
        long diff = end.getTime() - start.getTime();
        String diffFormatted = String.format("%02d:%02d:%02d",
                TimeUnit.MILLISECONDS.toHours(diff),
                TimeUnit.MILLISECONDS.toMinutes(diff)
                        - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(diff)),
                TimeUnit.MILLISECONDS.toSeconds(diff)
                        - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(diff)));

        hoursEditText.setText(diffFormatted);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM