0

I want to make a simple button which will start to loop a function every period of time which I can set. But not only it will start the loop, but also stop the loop if I click the button again. Is there anyway I can achieve this with a single button?

2 Answers 2

2

Here's how I'd do it

public class MainActivity extends AppCompatActivity {

    private Button btn;
    private View.OnClickListener runOnClickListener;
    private View.OnClickListener stopOnClickListener;


    void init() {
        Handler handler = new Handler();
        int duration = 5000;

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                foo();
                handler.postDelayed(this, duration);
            }
        };

        runOnClickListener = view -> {
            runnable.run();
            btn.setOnClickListener(stopOnClickListener);
        };

        stopOnClickListener = view -> {
            handler.removeCallbacks(runnable);
            btn.setOnClickListener(runOnClickListener);
        };

       btn.setOnClickListener(runOnClickListener);
    }

    void foo() {
        Log.i("foo", "foo");
    }

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

        btn = findViewById(R.id.btn);

        init();
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

runOnClickListener and stopOnClickListener gave me an error. Can you help me?
Could be because I'm using lambdas. Try using new View.OnClickListener() in place of view ->
Thank you so much! It works like a charm.
0

Yeah, give you a simple example.

First, create two constant values and one instance variable:

 //indicate whether or not the loop is running
    private boolean isRunning = false;

    //used for handler to send empty msg
    private final static int MSG_LOOP = 1;
    private final static long LOOP_INTERVAL = 5000;

Then create a Handler instance to handle the loop logic:

Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_LOOP:
                    doStuff();
                    break;
            }
        }
    };


    private void doStuff() {
        //after what you want to do is done, send another MSG_LOOP msg with delay
        handler.sendEmptyMessageDelayed(MSG_LOOP, LOOP_INTERVAL);
    }

And finally:

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isRunning) {
                    //cancel if any in the message queue
                    handler.removeMessages(MSG_LOOP);
                } else {
                    //if you do not want to start the loop immediately, then use: "sendEmptyMessageDelayed"
                    handler.sendEmptyMessage(MSG_LOOP);
                }

            }
        });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.