How to stop series of postDelayed handlers - java

I have a series of postDelayed handlers. I'm having trouble to set a mathode that stops the handlers when the user is tapping on the stop button at any time I he wants.
I'll appreciate any help someone able to provide.
Thanks
while (!lessonIsRunning) {
Handler handler0 = new Handler();
handler0.postDelayed(new Runnable() {
#Override
public void run() {
plate1.setVisibility(ImageView.VISIBLE);
plate2.setVisibility(ImageView.VISIBLE);
plate3.setVisibility(ImageView.VISIBLE);
}
}, 6000);
Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
apples1.setVisibility(ImageView.VISIBLE);
}
}, 9000);
Handler handler2 = new Handler();
handler2.postDelayed(new Runnable() {
#Override
public void run() {
plus1.setVisibility(TextView.VISIBLE);
}
}, 9250);
}
public void stopLesson(View V){
}

instead of writing the Runnable task in an anonymous way you must define it with a name, so that later you will have a link to it to remove:
//there is no need for multiple handlers
//handler must be declared outside all functions, in order for you to use it everywhere.
Handler handler = new Handler();
Runnable myFirstTask = new Runnable (){
#Override
public void run() {
plate1.setVisibility(ImageView.VISIBLE);
plate2.setVisibility(ImageView.VISIBLE);
plate3.setVisibility(ImageView.VISIBLE);
} };
Runnable mySecondTask = new Runnable(){
#Override
public void run() {
plus1.setVisibility(TextView.VISIBLE);
}
};
Runnable myThirdTask = new Runnable(){
#Override
public void run() {
apples1.setVisibility(ImageView.VISIBLE);
} }
//you can put different tasks on the same handler object
while (!lessonIsRunning) {
handler.postDelayed(myFirstTask,6000);
handler.postDelayed(mySecondTask,9250);
handler.postDelayed(myThirdTask,9000);
}
public void stopLesson(View V){
//notice that you don't need these, because the handlers are not recursive
//you don't have lines "handler.postDelayed(sameTask,someTime);"
//in your run Method of the runnable
if(handler!=null){
handler.removeCallbacks(myFirstTask);
handler.removeCallbacks(mySecondTask);
handler.removeCallbacks(myThirdTask);
//if this method is inside onPause or onDestroy add this line as well:
handler=null;
}
}

you can give
handler0.removeCallbacksAndMessages(null);
handler1.removeCallbacksAndMessages(null);
handler2.removeCallbacksAndMessages(null);
a try. The doc says when you submit a null token all callbacks and message are removed.

Related

Use so many Handler with postDelay method in android java

i'm working on kind animation program that i'm showing gif with Glide library but i'm using handlers too much for example showing loader and with another handler sync my sequence of showing others gif , i create like this
Handler handler2 = new Handler();
handler2.postDelayed(new Runnable() {
#Override
public void run() {
//showing gif file
}
}, 1000);
Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
}
}, 5000);
Handler handler3 = new Handler();
handler3.postDelayed(new Runnable() {
#Override
public void run() {
}
}, 6000);
and every one this handler are inside each other not exactly like above my question is :
Should i only create one instance from handler and use it ? like bloew
Handler handler = new Handler();
handler .postDelayed(new Runnable() {
#Override
public void run() {
}
}, 1000);
handler.postDelayed(new Runnable() {
#Override
public void run() {
}
}, 5000);
handler.postDelayed(new Runnable() {
#Override
public void run() {
}
}, 6000);
or i should do smoething else ?
i guess my application lagging a little not too much but i want to know the correct way to do it and if there is better way to handle this i appreciate any suggestion.
Should i destroy each handler and runnable after the task finished or not ?
Thanks in advance

Android - change UI immediately

After click button I would like to change its color, then wait one second and change its color back.
This is my code:
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
It doesn't work. I've checked it with more complex code and debugger and it looks like all UI changes are made collectively after finish this function.
I've found this thread: apply ui changes immediately and tried to put setBackgroundColor() and setClickable() into runOnUiThread function:
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
}
});
But it also doesn't work. What should I do?
Something like this :
private final Handler handler = new Handler();
public void click(final View view) {
view.setBackgroundColor(Color.parseColor("#0000ff"));
view.setClickable(false);
handler.postDelayed(() -> {
view.setBackgroundColor(Color.parseColor("#e2e2e2"));
view.setClickable(true);
}, 1000);
}
#Override protected void onPause() {
super.onPause();
handler.removeCallbacks(null);
}
The question is not very clear. However, I am trying to summarize the question that I have understood from your question.
You are trying to set a button's background color on clicking on it and change it back after some time. If this is the situation, then I think your idea of how threads work is wanting.
In your code, the button will change the color immediately as the sleep that you are using is running in another thread (other than UI thread). The code is executed correctly, however, you cannot see the effect of the Thread.sleep as its running in a separate thread.
So all you need to do here is to change the background color again inside the thread. Modify your code like the following.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
This should work.
I have created a demo trying to show what the code will do.
However, using Handler in case of updating UI elements in this specific case is recommended. Please see the comments below.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
}, 1000);
}
Not sure why that wouldn't work, but I've done something similar with
delayHandler = new Handler();
delayHandler.postDelayed(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//change stuff on ui
}
});
}
}, 1000);
if that doesn't work the only other functional difference in my code is that instead of btn being a final Button it's a private global variable in my activity.
Hope the following code will help :
btn.setBackgroundColor(Color.RED); // color you want for a second
new CountDownTimer(1000, 1000) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
btn.setBackgroundColor(Color.BLUE); //to change back color to prior state
}
}.start();
Try this,i think it's work for you..
final Button bPdf = findViewById(R.id.pdf);
bPdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
bPdf.setBackgroundColor(Color.parseColor("#0000ff"));
new CountDownTimer(1000, 50) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
bPdf.setBackgroundColor(Color.parseColor("#e2e2e2"));
}
}.start();
}
});

How to create a thread that lasts for a minute and takes input via button listener in android

I am working on an Android application in which I allow the users to enter text as many time they want in a single minute. But the thread is not terminating after a minute. My code:
public void startTimer(View view) throws Exception {
final Thread t = new Thread(new Runnable() {
final Button myButton = (Button) findViewById(R.id.myButton);
EditText mEdit = (EditText) findViewById(R.id.myTextInput);
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
myButton.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
Log.d("Tag", mEdit.getText().toString());
}
}
);
}
}
});
t.start();
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.schedule(new Runnable() {
#Override
public void run() {
t.interrupt();
}
},1, TimeUnit.MINUTES);
}
better use CountDownTimer http://developer.android.com/reference/android/os/CountDownTimer.html
In your solution you try do something with UI state in not main thread - this can be a issue.
Your thread isn't "taking input". It's continuously making and installing new onClick listeners.
You don't need a thread for what you're trying to do. You need a timer that goes off after one minute, and you need a listener that either accepts the input or rejects it depending on whether the timer has gone off yet or not.
You have two solutions you can do:
1st Solution:
You can simply use a handler.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
t.interrupt();
}
}, 60000);
2nd Solution:
You can also use a CountDownTimer.
new CountDownTimer(60000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
t.interrupt();
}
}.start();

Is it possible to perform separate network thread within a same activity without wait?

I am performing two class which is extending ASyncTask and both have different functions but because of the second class my first class is lagging. So what i want to know is, is there any better solution to code in such a way that both of the operation will perform the task without making other operation to wait?
Updated with code
For the first call in the onCreate()
new connection().execute(); //
Some task performed by the same class called
public class connection extends AsyncTask {
#Override
protected Object doInBackground(Object... arg0) {
//some operation
return value;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
String m = String.valueOf(o);
if (o != null) {
someoperation
} else {
edittxt.setTextColor(Color.RED);
edittxt.setText("No Internet Connection");
}
}
}
similarly i am performing the other class that i have.
You can use AsyncTask.executeOnExecutor with THREAD_POOL_EXECUTOR, the default executor is SERIAL_EXECUTOR.
You can create two separate threads and perform your operations. It will quarantine, that all operations will be performed async.
final Handler handler = new Handler();
Thread operation1 = new Thread(new Runnable() {
#Override
public void run() {
doOperation1();
handler.run(new Runnable(){
#Override
public void run() {
onPostExecute1();
}
});
}
});
Thread operation2 = new Thread(new Runnable() {
#Override
public void run() {
doOperation2();
handler.run(new Runnable(){
#Override
public void run() {
onPostExecute2();
}
});
}
});
operation1.start();
operation2.start();

Call function with timeout

i have a function
protected void updateLogs()
in my activity (MainActivity).
I need to call this function with delay. I cann't use this method https://stackoverflow.com/a/9166354/3883330 because i can't call function from other class, because it's not static function. Code with error:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
MainActivity.updateLogs();
}
}, 100);
How can i solve this?
This should work:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
updateLogs();
}
}, 100);
If it doesn't, declare a final object containing this:
final MainActivity main = this; // Just need to make it final
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
main.updateLogs();
}
}, 100);
As Carnal pointed out, it would be cleaner to declare an interface making the method to call public, however since you're calling it from an inner class, I think it's OK that way.

Categories

Resources