1

I have a button and i set a ontouchlistener to continuously execute a method but as i hold on to the button, it stops executing after 1 method call.

my method basically loops from 2 to 4 continuously.

Below is my code snippet.

broadcastButton = (Button) findViewById(R.id.broadcastButton);
broadcastButton.setText("Loop");
broadcastButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        broadcastmode = 1;
                        schedulePeriodicMethod();
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        broadcastmode = 0;
                        stopPeriodicMethod();


                }
                return true;
            }
        });

public void schedulePeriodicMethod() {
        exHandler.postDelayed(execution, 100);
    }

    public void stopPeriodicMethod() {
        exHandler.removeCallbacks(execution);
    }

    private Runnable execution = new Runnable() {
        @Override
        public void run() {
            connectDevice(flag);
            serialSend("C");
            flag++;
            if (flag > 4)
                flag = 2;
        }
    };

need help on where am i doing wrong that the program is not looping

5 Answers 5

3

Here is the simple method to loop a method continuously

//create a handler, override handle message of Handler
    private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {

// do yo stuffs here like UI update etc. 

//create a new message since a message will be consumed once as it       //delivered by handler after the delay
    Message message = new Message();
    message.what = msg.what;
// send the new message with handler
    myHandler.sendMessageDelayed(message, 150);
// 150 is time in milliseconds after which handler will give callback
    }
    };

// let us call the handler on touch of the view, set ontouch listener to //your desired view //on action down of on touch of the view, create a new message and pass it //to the handler

 @Override
    public boolean onTouch(View v, MotionEvent event) {
    switch(event.getAction()){
    case MotionEvent.ACTION_DOWN:
    Message message = new Message();
    myHandler.sendMessage(message);
    break;

// on action up of on touch of the view, remove the messages and call backs
//case MotionEvent.ACTION_UP:
    myHandler.removeCallbacksAndMessages(null);
    break;
    }
    return false;
    }
Sign up to request clarification or add additional context in comments.

Comments

1

change your starting function from

public void schedulePeriodicMethod() {
    exHandler.postDelayed(execution, 100);
}

to

public void schedulePeriodicMethod() {
    exHandler.post(execution);
}

and your runnable to :

private Runnable execution = new Runnable() {
    @Override
    public void run() {
        if (broadcastmode ==0) return;
        connectDevice(flag);
        serialSend("C");
        flag++;
        if (flag > 4)
            flag = 2;
        //call the runnable itself again, to keep execution going
        exHandler.postDelayed(execution, 100);
    }
};

And, as SGal said, your Thread.sleep is totally useless (btw, Thread.sleep in Android is not a good practice, especially on UI Thread)

2 Comments

Yeah. this method works. Thanks! It executes too fast, so i made the execution interval bigger. But if i need to wait for a certain event to trigger before executing/looping again, how can i do it?
set a condition on the recall. But if you have multiple conditions for looping, maybe you don't really need a loop but an on wanted execution? so just delete the recall & call schedulePeriodicMethod() when you want to.
0

i think schedulePeriodicMethod(); will call this one time:

public void schedulePeriodicMethod() {
        exHandler.postDelayed(execution, 100);
}

postDelayed() will run one time, so you need to recall it from the method itself

public void schedulePeriodicMethod() {
        exHandler.postDelayed(execution, 100);
        schedulePeriodicMethod();
}

3 Comments

tried calling the method again, app crashes once i press the button
can you post the stacktrace plz
ofcource! silly me. postDelayed is not blocking, you probably get stack overflow exception. You should call the method from your runnable, but I see @Apollo already posted the correct answer
0

this is because MotionEvent.ACTION_DOWN and MotionEvent.ACTION_MOVE Fire simultaneously when you Press the Button ,Use this approach

MOVE_THRESHOLD_DP = 20 * getActivity().getResources()
                .getDisplayMetrics().density;
    @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // TODO Auto-generated method stub
                    final int action = event.getAction();
                    switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        Log.d("TAG", "ON Down" + onMoveOccur);
                        onMoveOccur = false;
                        mDownPosX = event.getX();
                        mDownPosY = event.getY();

                      //your code 
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.d("TAG", "ON UP==" + onMoveOccur);

                        if (!onMoveOccur) {
                            //your code 
                        }
                        break;

                    case MotionEvent.ACTION_MOVE:
                        if (Math.abs(event.getX() - mDownPosX) > MOVE_THRESHOLD_DP
                                || Math.abs(event.getY() - mDownPosY) > MOVE_THRESHOLD_DP) {
                            onMoveOccur = true;
                        }
                        break;

                    default:
                        break;
                    }

                    return false;
                }
            });

Comments

0

Remove thread sleeping, because it doesn't do anything here and at best makes app skip 6 frames and at worst might even crash some devices since it stops main thread for 100ms

try {
    Thread.sleep(100);
} catch (InterruptedException e) {
    e.printStackTrace();
}

And make shadulePeriodicMethod() call it self like

public void schedulePeriodicMethod() {
        exHandler.postDelayed(execution, 100);
        if (broadcastmode == 1){
            schedulePeriodicMethod();
        }
}

1 Comment

tried calling the method itself. app crashes once i press the button

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.