I have a button that plays a rewarded ad, but it takes a few seconds for the ad to load. I want the button text to cycle between "Video loading." "Video loading.." and "Video loading..."
I've used the following runnable for this:
public Runnable CountDown = new Runnable() {
public void run() {
btnVideoStarts.setText("Video loading.");
handler.postDelayed(this, 1000);
btnVideoStarts.setText("Video loading..");
handler.postDelayed(this, 1000);
btnVideoStarts.setText("Video loading...");
if (rewardedInterstitialAd != null) {
btnVideoStarts.setText("Start video");
handler.removeCallbacks(CountDown);
}
}
};
The button shows "Video loading..." the whole time until it changes to "Start video".
Does anyone know why it's only showing those two labels?
I used to have a countdown timer that worked. Here's the code for it:
public Runnable CountDown = new Runnable() {
public void run() {
btnVideoStarts.setText("Video ready in " + String.valueOf(buttonCount)+"s");
buttonCount --;
handler.postDelayed(this, 1000);
if (buttonCount ==0) {
btnVideoStarts.setText("Start Video");
handler.removeCallbacks(CountDown);
}
}
};
The only problem was that the load times varied, so I figured I'd be better off just saying "Video loading..." rather than have the countdown expire before the video was ready.
I don't understand why the old code worked, but the new code doesn't. Can someone show me where I've gone wrong?
I'm not a 100 percent sure, but as fas as I understand handler.postDelayed() from
this explanation
Causes the Runnable r to be added to the message queue, to be run
after the specified amount of time elapses. The runnable will be run
on the thread to which this handler is attached. The time-base is
SystemClock.uptimeMillis(). Time spent in deep sleep will add an
additional delay to execution.
you will just add it to a queue, and execute it after 1000ms, so it won't delay the current execution, but will start the run() method again, after 1000ms.
To break down your code:
public Runnable CountDown = new Runnable() {
public void run() {
btnVideoStarts.setText("Video loading."); // sets the text to "Video loading."
handler.postDelayed(this, 1000); // adds itself to a queue, but won't stop the execution of this run through
btnVideoStarts.setText("Video loading.."); // sets the text to "Video loading.."
handler.postDelayed(this, 1000);
btnVideoStarts.setText("Video loading..."); // Finally sets the text to what you will always see, because the time window, between the text changes is to small
if (rewardedInterstitialAd != null) {
btnVideoStarts.setText("Start video");
handler.removeCallbacks(CountDown);
}
}
};
So essentially, you're generating a loop, with both of you're methods, as both will call themselves (delayed), your second method works, because you don't set the text twice in the method.
If you want to wait inside a Runnable, use Thread.sleep(ms) and a loop, that stops, when the video is loaded
Related
Lets say I have a ImageView that executes at a click of a Button:
final ImageView ball = new ImageView(v.getContext());
ball.setImageResource(R.drawable.ball_1);
gameConstraintLayout.addView(ball);
When I click that button, it first off makes the ball appears , creates and runs another thread that tell itself to sleep 1000 milliseconds sleep(long millis) then removes the ball by calling ConstrainLayout.removeView(view)
Here is the full minimal code:
final ImageView ball = new ImageView(v.getContext());
currentBullet.setImageResource(R.drawable.ball_1);
gameConstraintLayout.addView(ball);
ballAppears.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
final ImageView ball = new ImageView(v.getContext());
currentBullet.setImageResource(R.drawable.ball_1);
gameConstraintLayout.addView(ball);
Thread thread = new Thread() {
#Override
public void run() {
try {
sleep(1000);
contraintLayout.removeView(ball)
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
});
Problem is;
The ball appears on screen, the other thread successfully sleeps for 1000 milliseconds, but, It crashes when It tries to remove the ball from the constraint layout in the other thread.
Logcat:
android.view.ViewRootImpl$CalledFromWrongThreadException: **Only the original thread that created a view hierarchy can touch its views**.
at android.support.constraint.ConstraintLayout.removeView(ConstraintLayout.java:645)
at com.mobilegames.***.******.GameActivity$1$1.run(GameActivity.java:51)
The code that causes the problem is:
gameConstraintLayout.removeView(ball_1);
AS it seems,I cant access the Constraint layout from the other thread but, I can still change the X and the Y of the ball.
I even tried running that piece of code in the UI theard runOnUIThread(...), but to no avail.
Here is the runONUIThread code:
shootTank.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
final ImageView currentBullet = new ImageView(v.getContext());
currentBullet.setImageResource(R.drawable.bullet_model1);
gameConstraintLayout.addView(currentBullet);
Thread thread = new Thread() {
#Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
gameConstraintLayout.removeView(currentBullet);
}
});
}
};
thread.start();
}
});
Any possible solutions? Keep in mind that I change the X and Y's of the ball after every second.
AND YES, I did check other Questions. The answer in those ones said to simply run it on the UI thread, but of course I already tried that. If i run the sleep(long millis) into the UI thread, obliviously, the whole app would be irresponsible.
(This is not the full app; it was broken down into a much more simpler and understandable Question. I end up changing the ball's X and Y in the separate thread, but that inst what is causing the problem. Please tell me in comments if editing is necessary)
Sorry for small grammar mistakes
Use handler to perform your actions with some delay. For example:
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
gameConstraintLayout.removeView(currentBullet);
}
}, 1000); // here 1000 is delay in milliseconds (1sec)
I'm currently programming a mini game in java swing. I've got the GUI set up, and the game involves a sequence of numbers flashing up on screen and then disappearing - the user must then input the numbers again in the sequence they appeared.
When the numbers are initially displayed, I want them to display for 1-2 seconds, and then disappear, and have another number for 1-2 seconds etc.
However, I'm having issues with delaying the program whilst the number displays. I can't use Thread.sleep as it pauses the whole program with the hiding of previous numbers etc. It just doesn't work. I've tried every other suggestion I've come across, none of which have worked yet.
Anyone got anymore tips?
int delay = 5000; // delay in milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) { //...Perform a task... } };
Timer timer = new Timer(delay, taskPerformer);
timer.setRepeats(false);
timer.start(); // timer starts - after delay time your task gets executed
Source
You can use Thread.sleep()
The problem you having is probably because you are trying to update the UI from Swing's event dispatching thread. This is a thread that is reserved for Swing components and you should do exactly nothing in it except quick updates to the UI.
public void prog() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setText("1");
}
}
try {
Thread.sleep(5000);
} catch(Exception e) { }
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setText("2");
}
}
}
public static void main(String[] args) {
label = new JLabel("0");
prog();
}
JLabel label
The UI should remain responsive because of it's component interactions should be implemented in ActionListener's. But if you want to perform other work while waiting, or if the feature is contained in an ActionListener's actionPerfomed() method, you can kick off a new thread to sleep 5 seconds then update the UI. You could also perform some calculations that take 5 seconds to compute instead of sleeping without blocking the UI. The code would be:
(new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
} catch (Exception e) { }
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setText("2");
}
}
}
}).start();
I'm making an Android app that turns on/off the flash light after a specified interval, by the user. It works well except when the Timer object is re-created after calling the .cancel() method for the second time, it crashes the app every time.
Here's the initialization part:
Timer timer; //variable of Timer class
TimerTask timerTask; //variable of TimerTask class
And here's the method that is called when the button responsible to turn blinking on/off is pressed:
blink.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
delay = Integer.valueOf(startDelay.getText().toString());
gap = Integer.valueOf(blinkDelay.getText().toString());
if(!isBlinking) { //isBlinking is a boolean to know whether to stop or re-start timer
timer = new Timer(); //I'm creating an object of Timer class every time.
isBlinking = true;
timer.schedule(timerTask, delay, gap);
}
else{
isBlinking = false;
stoptimertask(); //this will cancel the 'timer' and make it null.
}
}
});
The 'stoptimertask()' method from above code has:
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
I'm setting the 'timertask' variable of TimerTask class from the method shown below. It is called in the onCreate() method of the main activity:
public void initializeTimerTask() {
timerTask = new TimerTask() { //This is passed as the first argument to the timer.schedule() method
public void run() {//Basically turns on/off flash. Works well.
if(!state) {
turnOnFlash();
state = true;
}
else {
turnOffFlash();
state = false;
}
}
};
My question is that why does the app crash when I press the blink button the third time?
When it is pressed for the first time, isBlinking is false, so the if block executes creating a new object of the Timer class and starting the timer.
When it is pressed for the second time, stoptimertask() is called which cancels the timer and sets timer variable to null.
When it is pressed again for the third time with different values for delay and gap, a new object of Timer class should be created, but the application crashes unexpectedly with a "Unfortunately the app has stopped" error.
Where am I going wrong?
You will have to purge as well.
timer.cancel();
timer.purge();
Don't forget to purge after cancel.
Your code must be for stoptimertask() method.
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer.purge();
timer = null;
}
}
Related Link:
Android timer? How-to?
How to set a timer in android
UPDATE:
Since Timer creates a new thread, it may be considered heavy,
if all you need is to get is a call back while the activity is running a Handler can be used in conjunction with this link
How to set a timer in android
I am trying to create a circuit timer using the countdown timer. When the thread is sleeping I want the text to display "Change!" and this to display for 5 seconds before the countdown timer starts again. I am unsure how to get this working. I know the thread is sleeping and so wont display the "Change!" until after it has woke up again after the 5 seconds. But I cannot understand how to get it working the way I wish it to. Can anyone help me solve this issue?
public void onFinish()
{
// Text to be displayed when thread is sleeping
time.setText("Change!");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (numberOfCircuits != 15)
{
start();
numberOfCircuits++;
}
else
{
countDownTimer.cancel();
}
}
Instead of making the main thread sleep(you are likely to get an ANR dialog), you can use a Timer which can notify you of your 5sec lapse and you can schedule your CountDownTimer again.
public void onFinish()
{
// Text to be displayed when thread is sleeping
time.setText("Change!");
new Timer("Sleeper").schedule(new TimerTask() {
#Override
public void run() {
if (numberOfCircuits != 15)
{
start();
numberOfCircuits++;
}
else
{
countDownTimer.cancel();
}
}
}, 5000); // 5 sec delay
}
My Android App works fine, except the end sequence. Its a game and at the end the screen shows the score:
TextView allscores = new TextView(this);
allscores.setText("Your score: "+ mypoints);
Next I want the GUI to slowdown for a few seconds so the user has time to take in the information. Maybe 2 or 3 secs is fine.
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
layout.removeAllViews();
Bear in mind, I'm new to thread programming. All this is done on the UI thread, I have no other threads running.
Next I put in a final splash screen ending:
AnView animator = new AnView(this);
layout.addView(animator);
where AnView is my own extension of View.
All in all it runs great. Problem is the thread sleeps for 3 seconds without showing my final score. I don't know why. I don't know why it doesn't show my final score before sleeping. It actually goes blank, indicating that it removed all views and then slept.
You're not seeing the score because sleeping on the UI thread prevents the layout and drawing operations that make your text changes visible. Never sleep on the UI thread.
Using a new thread for this is overkill. Use a Handler and the postDelayed method to make something happen after a delay.
private final Handler mHandler = new Handler();
Then when you want to do something later,
mHandler.postDelayed(new Runnable() {
public void run() {
doDelayedThing();
}
}, 3000);
As others have pointed out: don't use sleep in the UI thread.
What you should do instead is described here:
http://developer.android.com/guide/appendix/faq/commontasks.html#threading
in section "Handling Expensive Operations in the UI Thread"
It is not recommended to ever sleep the main UI thread. Try something like this:
new Thread(new Runnable(){
//do work here
});
Or you could try using a Toast popup for the score.
You can also use Timer to wait 3 seconds, which will start a new thread after the time runs out.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
AnView animator = new AnView(this);
layout.addView(animator);
}
}, 3000);