While there must be a better tactic of completing a countdown I have set up in my application, it seemed clear to me that using Thread.sleep(1000) between every digit would work. It did not and I still do not have any other solution. When I run the app, the countdown goes from 5, straight to 1 in 1 second.
This is my code:
bBegin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bBegin.setText("5");
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
}
bBegin.setText("4");
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
}
bBegin.setText("3");
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
}
bBegin.setText("2");
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
}
bBegin.setText("1");
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
}
}
Thanks, I hope this problems helps other noobs like me (and no worries, I did check the site for a previous solution)
Thread.sleep(1000); Bad! You are calling sleep() on the UI thread which you alsmost, if ever, never want to do. The UI will sleep for that amount of time. Use CountDownTimer instead.
CountDownTimer Docs
There are certainly other ways but this one should be good to accomplish what you want.
Example
In your case you might use a CountDownTimer something like this.
Create an inner class
private class MyCountDown extends CountDownTimer
{
long duration, interval;
public MyCountDown(long millisInFuture, long countDownInterval)
{
super(millisInFuture, countDownInterval);
duration = millisInFuture;
interval = countDownInterval;
int secs = 5; // varaible for counter to be placed in TextView
start();
}
#Override
public void onTick(long duration)
{
bBegin.setText(String.valueOf(secs));
secs = secs - 1;
}
#Override
public void onFinish() {
secs = 5; // reset counter if needed or do anything else you need when countdown is over
}
And call it in onClick() like
MyCountDown timer = new MyCountDown(5000, 1000); // local variable but might want to make it a member variable
Sleep doesn't "skip" anything - instead, this code prevents the UI from updating until after the method ends (after it sleeps all 5 times).
At some point after the onClick method ends - and the UI dispatch can resume operation - the UI is updated. When this update occurs the display is updated with the last value assigned, which leads to the incorrect conclusion that code was "skipped". However, all of the code in the method ran.
This leads us to a very important rule: do not sleep on the main-UI thread. Doing so blocks user interaction and it blocks display updates because it blocks the UI event/dispatch queue. All standard UI callbacks, such as click listeners, occur on the UI thread.
Where sleep is required - as in the case of games and custom canvases, say - the sleep is done on a different (non UI) thread so that it does not cause such primary UI blocking behavior.
**As in the attached code snippet it is showing user thread is trying to update UI Thread.which is not a good practice..
i have done same using the concept of Handler.
the code snipper is ..**
public class MainActivity extends Activity {
TextView tv;
Button b1;
Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView) findViewById(R.id.textView1);
b1=(Button) findViewById(R.id.button1);
handler= new Handler();
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Runnable r=new Runnable() {
int mynumber=5;
#Override
public void run() {
while(mynumber >0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
public void run() {
tv.setText("remaining time is "+mynumber );
}
});
mynumber--;
}
}
};
new Thread(r).start();
}
});
}
}
Related
I want to set network status in TextView, which I want to repetitively call method and set in background, so I used AsyncTask class with infinite loop
class setNetworkText extends AsyncTask
{
#Override
protected Object doInBackground(Object[] params) {
for(;;)
{
if(isNetworkConnected()) //check internet connection and if found it return true
setOnline(); // it set my TextView text to Online
else
setOffline(); // it set my TextView text to Offline
Thread.sleep(2000);
}
return null;
}
}
but it is not working, it stops my application.
Android will (in most versions) only execute one AsyncTask at a time - so if you keep blocking in doInBackground of one AsyncTask, no other AsyncTasks will run, thus blocking your application.
Take a look at using Handler.postDelayed or using a TimerTask. They are more suited for repeating actions.
You can not use AsyncTask to do that. You should use Handler to schedule a task periodically.
// Create the Handler
Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnableTask = new Runnable() {
#Override
public void run() {
if(isNetworkConnected())
setOnline();
else
setOffline();
}
};
// Call on main thread (for example, inside onResume())
#Override
protected void onResume() {
super.onResume();
handler.postDelayed(runnableTask, 2000);
}
// Remember to unregister it onPause()
#Override
protected void onPause() {
super.onPause();
handler.removeCallbacks(runnableTask);
}
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
//check something on time interval here 1 second
}
public void onFinish() {
//when your task done here 3 second is time to end
}
}.start();
explanation
CountDownTimer(long millisInFuture, long countDownInterval)
millisInfuture will be how long you want to run the task and countDownInterval is the interval in your case it is 2 seconds
I want to make an application about mini game.
Detail : In 2 seconds you must to answer a question if you don't answer or the answer is wrong -> Game Over . But if your answer is true the Timer will reset become 0 and countdown again with diffirent question.
I have already seen many code about timer in website but I don't understand clearly about it :(
So I want to ask : How can i set up a timer run only 2 seconds and how can i reset it and continue with a new question ?
Please help me.
you can use CountDownTimer in android like this:
public class Myclass {
myTimer timer =new myTimer(2000,1000);
public void creatQuestion(){
timer.start();
//method you init question and show it to user
}
public void getUserAnswer(/*evry thing you expected*/)
{
//if answer is true call timer.start()
//else call timer.onFinish(); to run onfinish in timer
}
public class myTimer extends CountDownTimer {
public myTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
// you can update ui here
}
#Override
public void onFinish() {
this.cancel();
//fire game over event
}
}
}
i hope it make you satisfy
I've done something similar using Thread/Runnable.
Thread t = new Thread(new Runnable() {
public void run() {
final long startTime = getTime();
final long maxEndTime = startTime + 2000L;
try {
while (shouldContinueWaiting()) {
if (getTime() > maxEndTime) {
throw new TimeoutException();
}
sleep();
}
} catch (InterruptedException e) {
handleInterrupt();
} catch (TimeoutException e) {
handleTimeout();
}
}
boolean shouldContinueWaiting() {
// Has the user already answered?
}
void handleInterrupt() {
// The user has answered. Dispose of this thread.
}
void handleTimeout() {
// User didn't answer in time
}
void sleep() throws InterruptedException {
Thread.sleep(SLEEP_DURATION_IN_MILLIS);
}
void getTime() {
return System.currentTimeMillis();
}
then you can start/restart the thread by:
t = new Thread(same as above...);
t.start();
and stop by:
t.interrupt();
We want to use the Timer class.
private Timer timer;
When you're ready for the timer to start counting -- let's say it's after you press a certain button -- do this to start it:
timer = new Timer();
timer.scheduleAtFixedRate(incrementTime(), 0, 100);
The first line is us creating a new Timer. Pretty standard. The second line, however, is the one I wanted you to see.
incrementTime() is a method that is called at the end of every "tick" of the clock. This method can be called whatever you want, but it has to return an instance of TimerTask. You could even make an anonymous interface if you want, but I prefer moving it off into its own section of code.
The 0 is our starting location. We start counting from here. Simple.
The 100 is how large a "tick" of the clock is (in milliseconds). Here, it's every 100 milliseconds, or every 1/10 of a second. I used this value at the time of writing this code because I was making a stopwatch application and I wanted my clock to change every 0.1 seconds.
As for your project, I'd suggest making the timer's task be your question switch method. Make it happen every 2000 milliseconds, or 2 seconds.
You can use a Handler.
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//this will happen after 2000 ms
}
}, 2000);
Maybe this can help you:
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
// FIRE GAME OVER
handler.postDelayed(this, 2000); // set time here to refresh textView
}
});
You can fire your game over after 2000 milliseconds.
If you get the question correct -> remove callback from handler and reset it when the next question starts.
I am trying to develop a game like matching small pictures.My problem is that i want to finish the game after a time period.For instance in level 1 we have 10 seconds to match picture.I want to display remaining time also.I will be thankful for any help.
Since you also want to show the countdown, I would recommend a CountDownTimer. This has methods to take action at each "tick" which can be an interval you set in the constructor. And it's methods run on the UI Thread so you can easily update a TextView, etc...
In it's onFinish() method you can call finish() for your Activity or do any other appropriate action.
See this answer for an example
Edit with more clear example
Here I have an inner-class which extends CountDownTimer
#Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.some_xml);
// initialize Views, Animation, etc...
// Initialize the CountDownClass
timer = new MyCountDown(11000, 1000);
}
// inner class
private class MyCountDown extends CountDownTimer
{
public MyCountDown(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
frameAnimation.start();
start();
}
#Override
public void onFinish() {
secs = 10;
// I have an Intent you might not need one
startActivity(intent);
YourActivity.this.finish();
}
#Override
public void onTick(long duration) {
cd.setText(String.valueOf(secs));
secs = secs - 1;
}
}
#nKn described it pretty well.
However, if you do not want to mess around with Handler. You always can delay the progress of the system code by writing:
Thread.sleep(time_at_mili_seconds);
You probably need to surround it with try-catch, which you can easily add via Source-> Surround with --> Try & catch.
You can use postDelayed() method of Handler...pass a Thread and specific time after which time the Thread will be executed as below...
private Handler mTimerHandler = new Handler();
private Runnable mTimerExecutor = new Runnable() {
#Override
public void run() {
//here, write your code
}
};
Then call postDelayed() method of Handler to execute after your specified time as below...
mTimerHandler.postDelayed(mTimerExecutor, 10000);
I have an app that runs 2 threads in loops. 1st one is updating a graph in 1s interval and the second one is updating another graph at 60s interval. The second task is taking a long time since it is quering some server in the internet 3 times that might not always be available and even if it is it will take up to 5-7s to execute.
What is happening is when I launch the second thread it will pause execution of the first one and that is not what I want, I wish both run concurrently. Here in the Youtube video you can see the results of the app running. http://youtu.be/l7K5zSWzlxI
"thread_updater1s" is running a green graph, large readout, and a timer in the corner so you clearly see it stalls for 11 seconds.
1)First of all why is that happening? how to fix it?
2)I'm aware that I might not launch the threads properly at all. I had hard time understanding how to make something to run in a interval loop in Java and my code worked fine for one graph/tread. Now when I have 2 loops in separate threads I don't know why they are not executing concurrently.
Here is the code:
public class LoopExampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
thread_updater1s.start();
thread_updater2.start();
}// end of onCreate
final Runnable r1s = new Runnable() {
public void run() {
do_1s_updates(); // those are very quick http calls to the local API server
} // to get data nessessary for some plot.
// They have 1s timeout as well but rarely timeout
};
final Runnable r2 = new Runnable() {
public void run() {
do_large_updates(); //This makes 7 long call over the Internet to the slow https
//server once every 60s. Has 10s timeout and sometimes takes as much as
//7s to execute
}
};
Thread thread_updater1s = new Thread() {
#Override
public void run() {
try {
while (true) {
handler.post(r1s);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread_updater2 = new Thread() {
#Override
public void run() {
try {
while (true) {
handler2.post(r2);
sleep(60000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
PS. please be forgiving and informative I only code Java for 15 days so far with absolutely no prior experince or lesson.
You need to make the http requests in the threads (not the posted runnables). Then, when you have the data downloaded, you create a runnable with that data that will update the graph and post that runnable to be executed by the UI thread. Here is an example:
public class LoopExampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
thread_updater1s.start();
thread_updater2.start();
}// end of onCreate
Thread thread_updater1s = new Thread() {
#Override
public void run() {
try {
while (true) {
final Object data = getDataFromServer1();
handler.post(new Runnable() {
#Override
public void run() {
updateGraph1(data);
}
);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread_updater2 = new Thread() {
#Override
public void run() {
try {
while (true) {
final Object data = getDataFromServer2();
handler.post(new Runnable() {
#Override
public void run() {
updateGraph2(data);
}
);
sleep(60000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Obviously, change that final Object data by the appropriate class that represents your data downloaded.
handler.post pushes the runnable onto the main (UI) thread's message queue for execution on the main thread.
So what you're doing is every sleep interval, you're sending a message to the main thread to run the function. Clearly, the main thread can't run 2 things at once, so that's why one runnable is delayed for the next one.
You probably want to do the work of the runnable in the separate threads - why did you start using a handler? What happens if you call do_1s_updates and do_large_updates directly instead of through the handler & runnable?
I want to create a paint and update loop in android for game animation on a canvas but I am having trouble as I can't seem to get the threading to work appropriately. It seems to crash almost immediately. Here is what I have tried:
// Create the thread supplying it with the runnable object
Thread thread = new Thread(runnable);
// Start the thread in oncreate()
thread.start();
class runner implements Runnable {
// This method is called when the thread runs
long wait = 1000;
public void run() {
update();
}
public void update()
{
try{
Thread.currentThread();
//do what you want to do before sleeping
Thread.sleep(wait);//sleep for 1000 ms
//do what you want to do after sleeping
}
catch(InterruptedException ie){
//If this thread was interrupted by another thread
}
run();
}
}
Also when I drop the wait down lower it crashes faster.
Is there a more appropriate way to approach this?
Changed to this:
class runner implements Runnable {
// This method is called when the thread runs
long wait = 10;
boolean blocked = false;
public void run() {
if(!blocked){
blocked = true;
paint();
}
}
public void paint()
{
update();
}
public void update()
{
try{
Thread.currentThread();
//do what you want to do before sleeping
Thread.sleep(wait);//sleep for 1000 ms
//do what you want to do after sleeping
}
catch(InterruptedException ie){
//If this thread was interrupted by another thread
}
paint();
}
}
This results in the same error... :/
Well the first thing I notice is that run calls update and update calls run. This is going to cause a NO PUN INTENDED Stack Overflow. They call each other until the stacks fills up. Then it should crash.
You are missing your 'loop'.
You should NOT call run manually on an already started thread.
public void run()
{
while (true)
{
// do whatever
Thread.sleep(wait);
}
}
I would not actually use the above either, I'd use a Timer or Android equivalent. You should get the concept from this though.