Android: Handler.postDelayed doesn't stop - java

I am unable to stop handler.postDelayed from example below. It simply continues to do function after 1 second, and doesn't stop when switch is off:
mySwitch.setChecked(false);
mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
myClient.SendData("AA");
handler.postDelayed(this, 1000);
}
};
if (isChecked){
handler.postDelayed(r, 1000);
}
else {
handler.removeCallbacks(r);
}
}
});

and doesn't stop when switch is off:
that's because you are instantiating r every time the callback is being called. Move
final Runnable r = new Runnable() {
public void run() {
myClient.SendData("AA");
handler.postDelayed(this, 1000);
}
};
outside the callback. In the scope of your method or of the class

Related

Why is there no delay on Handler?

I have created a handler for an alert that should activate for 4 seconds, stops for 4 seconds, and activates again. When i put it in the if statement, it doesn't work; the alert keeps playing, stops for less than a second and continues activating again without the delay. Wonder if anyone knows why is it happening and what should i do to correct it. Thank you.
private Handler handler2 = new Handler();
private Runnable startalert = new Runnable() {
#Override
public void run() {
alert2.start();
handler2.postDelayed(this, 4000);
}
};
#Override
public void onLocationChanged(Location location) {
if (location == null) {
speedo.setText("-.- km/h");
}
else {
currentSpeed = location.getSpeed() * 1.85f; //Knots to kmh conversion.
speedo.setText(Math.round(currentSpeed) + " km/h");
}
if (currentSpeed <=4.99) {
background.setBackgroundColor(Color.GREEN);
handler2.removeCallbacks(startalert);
} else if(currentSpeed >=5.00 && currentSpeed <=9.99) {
background.setBackgroundColor(Color.YELLOW);
handler2.removeCallbacks(startalert);
} else if(currentSpeed >=10.00) {
background.setBackgroundColor(Color.RED);
startalert.run();
}
}
Instead of 'this', use runnable object.
private Runnable startalert = new Runnable() {
#Override
public void run() {
alert2.start();
handler2.postDelayed(startalert, 4000);
}
};
Another method:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
alert2.start();
handler.postDelayed(this, 4000);
}
}, 4000);

Enable and Disable Button using Timer in Android

I have two Buttons in main View, Button1 and Button2. How can I disable Button1 for specific time period after that time period it should Enable again.
Use a countdown Timer.
Say you have button button1 ;
button1.setEnabled(false);
new CountDownTimer(5000, 10) { //Set Timer for 5 seconds
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
button1.setEnabled(true);
}
}.start()
Aba: Applied correct View.setEnabled method.
Here is an example:
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
#Override
public void run(){
button.setEnabled(false);
}
}, 5000);
Rest, figure out yourself.
You can call this method. Try this once
private void blink(){
final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
int timeToBlink = 5000;
try{
Thread.sleep(timeToBlink);
}catch (Exception e) {
}
handler.post(new Runnable() {
#Override
public void run() {
if(button.isEnabled()){
button.setEnabled(false);
}else{
button.setEnabled(true);
}
blink();
}
});
}
}).start();
}
By calling this method You will get the effect you wanted
private fun initButton() {
button.setOnClickListener {
it.isEnabled = false
it.postDelayed({ it.isEnabled = true }, 3000)
//do stuff
}
}
This works in Kt, does require a handler tho
In the simplest way
yourView.setEnabled(false);
yourView.postDelayed(() -> yourView.setEnabled(true), 5000); // Wait for 5 seconds

Execute function after 5 seconds in Android

I am new in android development and now my launcher activity show only 5 seconds and after that I want to check the user is logged in or not function and perform the actions.
here is my code.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exactPreferences = getSharedPreferences("ExactPreference",MODE_PRIVATE);
setContentView(R.layout.activity_landing_page);
session = exactPreferences.getString(Model.getSingleton().SHARED_SESSION_ID,null);
Log.i("Session Id",session);
displayData(); // I want to perform this function after 5 seconds.
}
private void displayData() {
if(session.equals("")){
Intent loginIntent = new Intent(LandingPage.this,
LoginActivity.class);
startActivity(loginIntent);
Log.i("User Logged In", "False");
}
else
{
Intent objIntent = new Intent(LandingPage.this,
IndexPageActivity.class);
startActivity(objIntent);
Log.i("User Logged In", "True");
}
}
You can use the Handler to add some delay.Call the method displayData() as below so that it will be executed after 5 seconds.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
displayData();
}
}, 5000);
Note : Do not use the threads like Thread.sleep(5000); because it will block your UI and and makes it irresponsive.
Assign millisDelayTime variable with the milliseconds you desire to cause a delay. mActivity is an object of Activity for providing Application Context. In your case millisDelayTime should be initialized with 5000
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//your code here
}
}, millisDelayTime);
}
});
Use a CountDownTimer
// There's a TextView txtCount in Main Activity
final int secs = 5;
new CountDownTimer((secs +1) * 1000, 1000) // Wait 5 secs, tick every 1 sec
{
#Override
public final void onTick(final long millisUntilFinished)
{
txtCount.setText("" + (int) (millisUntilFinished * .001f));
}
#Override
public final void onFinish()
{
txtCount.setText("GO!");
finish();
// Time's up - Start the Login Activity
final Intent tnt =
new Intent(getApplicationContext(), LoginActivity.class);
startActivity(tnt);
}
}.start();
Since, Handler is now deprecated so use this code :
new Handler(Looper.myLooper()).postDelayed(new Runnable() {
#Override
public void run() {
//do what you want
}
}, 5000);
Try this, code create CountDownTimer with one tick
timer = new CountDownTimer(5000, 5000)
{
public void onTick(long millisUntilFinished)
{
}
public void onFinish()
{
displayData();
}
};
timer.start();
long delay = 1000;
long period = 50000;
Timer task = new Timer();
task.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
getDriver(sessionManager.getKEY(), ride_id);
}
}, delay, period);
For kotlin way
Handler().postDelayed({
//do something
}, 5000)
When possible, try to avoid using postDelayed. It is a bad practice, since it can lose the reference to the objects that you want to draw on your screen and cause a NPE. Use a Handler instead. First of all, create a global variable Handler in which you will have to "handle" the logic for your code. Do so by using the function handleMessage.
Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
if(msg.what == 1){
// your code here
}
}
};
Then, wherever you want to execute it, just call the function:
// 1 is the ID of your process
handler.sendEmptyMessageDelayed(1, 5000);
Please remember that in the onDestroyView method (in a Fragment) or the onDestroy (in an Activity) you will have to call
handler.removeMessages(1)
The best option to achieve this is using a Handler:
int TIME = 5000; //5000 ms (5 Seconds)
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
function(); //call function!
}
}, TIME);

Do action while long click

Hello I am trying to perform some actions while the user is holding down a button.
My problem is that my Runnable wont "run".
Here is my code:
#Override
public boolean onLongClick(View v) {
final Runnable r = new Runnable()
{
public void run()
{//do the forwarding logic here
int test = 0;
if(holdingDown)
test++;
else
return;
Log.i("test", test+"");
}
};
r.run();
}
return false;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
{
holdingDown= false;
Log.i("holdingDown", "false");
break;
}
}
return false;
}
The onTouch is for detecting when the user stop pressing the button. When I look at my logs I see at that the Runnable runs only once.
My test log get only the value 1.
The log call for Log.i("holdingDown", "false") is getting triggered at the right time, only when I stop touching the button.
Why is it that my Runnable won't run? Thanks.
EDIT:
I tried this code:
#Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
holdingDown = true;
new Thread(new Runnable() {
#Override
public void run() {
if(holdingDown)
{
int test = 0;
test++;
Log.i("test", test+"");
}
else
return;
}
}).start();
return false;
}
Its till not working.
You could try using a Thread instead of a Runnable like this:
Thread thread = new Thread() {
#Override
public void run() {
//code you want to run on long press
} };
thread.start();
OR
You could try putting the Runnable inside a Thread like this:
Thread thread = new Thread(new Runnable() {
public void run() {
// code you want to run on long press
}
});
thread.start();
UPDATE: - try this?
#Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
holdingDown = true;
new Thread(new Runnable() {
#Override
public void run() {
if (holdingDown) {
int test = 0;
test++;
Log.i("test", test + "");
} else {
Log.i("test", "else");
}
return;
}
}).start();
return false;
}
You don't do r.run() to start a thread, that only runs it once.
You either do new Thread(r).start(); or you use a ScheduledExecutorService.
You can create a class called HoldingDown overriding Runnable and instantiate a Thread object passing a new instance of your HoldingDown and call the start method.
Also, you can use the mousePressed and mouseReleased events of MouseListener.
You should start a new Thread in your mousePressed, store the instance somewhere and stop it on mouseReleased.
See the documentation for more details.

Handler with ProgressBar

Im am trying to create a delayed action, when I touch the Display for more than 5 Seonds.
I am using a Handler and a Runnable for this, using handler.postDelayed(runnable, 5000);
I also want a ProgressBar, to show, when the Handler will kickoff. From researching i found, that i have to Override the handleMessage() method.. this is what i tried.
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progress.setProgress(progress.getProgress() + 100);
sendEmptyMessageDelayed(0, 100);
}
};
private Runnable runnable = new Runnable() {
public void run() {
playAlarm();
}
};
...
progress = (ProgressBar) findViewById(R.id.progressBar1);
...
#Override
public boolean onTouchEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
// Execute Runnable after 5000 milliseconds = 5 seconds.
progress.setProgress(0);
handler.postDelayed(runnable, 5000);
mBooleanIsPressed = true;
}
if (e.getAction() == MotionEvent.ACTION_UP) {
if (mBooleanIsPressed) {
mBooleanIsPressed = false;
progress.setProgress(0);
handler.removeCallbacks(runnable);
}
}
return true;
}
It is not crashing. But the ProgressBar is simply not showing anything.
if you want to use a handler there some things missing, this should work (not tested):
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progress.setProgress(progress.getProgress() + 100);
if (mBooleanIsPressed)
sendEmptyMessageDelayed(0, 100);
}
};
private Runnable runnable = new Runnable() {
public void run() {
playAlarm();
}
};
...
progress = (ProgressBar) findViewById(R.id.progressBar1);
...
#Override
public boolean onTouchEvent(MotionEvent e) {
// only start your handler if the view isn't touched
if (e.getAction() == MotionEvent.ACTION_DOWN && !mBooleanIsPressed) {
// Execute Runnable after 5000 milliseconds = 5 seconds.
progress.setProgress(0);
handler.postDelayed(runnable, 5000);
// send the first empty message, which will be handled...
sendEmptyMessageDelayed(0, 100);
mBooleanIsPressed = true;
}
if (e.getAction() == MotionEvent.ACTION_UP) {
if (mBooleanIsPressed) {
mBooleanIsPressed = false;
progress.setProgress(0);
handler.removeCallbacks(runnable);
}
}
return true;
}
feel free to ask if you have any questions

Categories

Resources