I am making a statistical counter that counts upto a certain number (say 60) and the user should see each and every number as it increments on the screen.
TextView display1;
public int stat1 = 60;
public void doSomething(View v){
display1 = (TextView)findViewById(R.id.stat);
for(int i=0;i<=stat1;i++){
String temp = (String.valueOf(i));
for(long j=0;j<1000000;j++);
Log.d("PATO","Value - "+i);
display1.setText(temp);
display1.invalidate();
}
}
However, this code only displays the final number i.e. 60 on the screen even though I can see the increments on the debug screen.
Please find the below solution
protected static void startTimer() {
isTimerRunning = true;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
elapsedTime += 1; //increase every sec
mHandler.obtainMessage(1).sendToTarget();
}
}, 0, 1000);
};
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
}
}
Above code must work...
Note:mHandler must be created in your main thread.
As your counter is fast . so display1.setText() is overlapping the value, so you cannot see the previous value, so you can do this :
for(int i=0;i<=stat1;i++){
String temp = (String.valueOf(i));
Log.d("Value",temp);
Thread.sleep(1000);
for(long j=0;j<1000000;j++);
Log.d("PATO","Value - "+i);
display1.setText(temp);
display1.invalidate();
}
}
Related
This question already has answers here:
Update TextView Every Second
(11 answers)
Closed 4 years ago.
i want to update my textview every second.
on button click i am calling one method,
loopMethod(milli); //suppose milli= 50000 i.e 50 sec.
so my loopMethod(int m) is as follows:
public void loopMethod(int m){
timer=(TextView) findViewById(R.id.timerText);
if(m>=1000){
try {
timer.setText(""+m);//timer is a textview
System.out.println(m);
m=m-1000;
Thread.sleep(1000);
} catch(InterruptedException ex) {
ex.printStackTrace();
}
loopMethod(m);
}
}
so what i am expecting is, my timer textview should print the value of m every second.
but i am getting only console output i.e system.out.println(m)...
printing value on console working fine...
but its not updating my textview at all
You can use following code:
Runnable updater;
void updateTime(final String timeString) {
timer=(TextView) findViewById(R.id.timerText);
final Handler timerHandler = new Handler();
updater = new Runnable() {
#Override
public void run() {
timer.setText(timeString);
timerHandler.postDelayed(updater,1000);
}
};
timerHandler.post(updater);
}
In this line:
timerHandler.post(updater);
time will set for the first time. i.e, updater will execute. After first execution it will be posted after every 1 second time interval. It will update your TextView every one second.
You need to remove it when the activity destroys, else it will leak memory.
#Override
protected void onDestroy() {
super.onDestroy();
timerHandler.removeCallbacks(updater);
}
Hope it will help you.
You should use RxJava library to do so:
Subscription s =
Observable.interval(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(v -> {
// update your ui here
}, e -> {
});
// call when you no longer need an update:
if (s != null && !s.isUnsubscribed()){
s.unsubscribe();
s = null;
}
That's it. Do NOT use .postDelay(), Timer because it is error prone.
You might want to consider using the Chronometer class: https://developer.android.com/reference/android/widget/Chronometer.html
just use timer.start(); on the button click
Using handler can be used like this
TextView timer;
int m =0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timer=(TextView) findViewById(R.id.timerText);
Handler handler = new UpdateHandler();
m = 10;
handler.sendEmptyMessageDelayed(1, 1000);//start after 1000
}
class UpdateHandler extends Handler{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
timer=(TextView) findViewById(R.id.timerText);
timer.setText("Text :" +m);
m = m-1000;
sendEmptyMessageDelayed(1, 1000); //seng again after 1000
//add some stop logic
break;
default:
break;
}
}
}
Try this code Initialize textview in
onCreate
timer=(TextView) findViewById(R.id.timerText);
public void loopMethod(int m){
if(m>=1000){
try {
System.out.println(m);
m=m-1000;
final ScheduledThreadPoolExecutor c = new ScheduledThreadPoolExecutor(1);
c.schedule(new Runnable() {
#Override
public void run() {
timer.setText(""+m);//timer is a textview
c.shutdownNow();
}
}, 1, TimeUnit.SECONDS);
} catch(InterruptedException ex) {
ex.printStackTrace();
}
loopMethod(m);
}
}
I've added some logics to stop the Timer. If you have any qyestion, ask freely
private int m = 0;
private int milliseconds = 1000;
public void loopMethod(int m){
timer=(TextView) findViewById(R.id.timerText);
Timer t = new Timer();
//schedule a timer
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
timer.setText(String.valueOf(m));//avoid using composite string in the setText
System.out.println(String.valueOf(m));
//remove from the total the amount of millisecond passed
m=m-milliseconds;
if(m <= milliseconds) { //or <= what you want
//stop the timer repeatitions
t.cancel();
}
}
});
}
//"0" is the amount of time to wait for the timer to start
//"milliseconds" is the duration
},0,milliseconds);
}
Add
For a correct analysis you should add more infos in your question. the problem of not-updating textview might be caused by the setText("" + int) because it's always better to avoid the setText with an int. I edited it with String.valueOf, but if it's not working you should add the xml and the onCreate
Hope this helped
I have created timer for seconds.
public class TimerForSeconds extends AppCompatActivity {
private int seconds = 60;
private TextView tvTimer;
private Handler mHandler;
private Runnable runnable = new Runnable() {
#Override
public void run() {
if(seconds == 0){
mHandler.removeCallbacks(runnable);
}
else{
tvTimer.setText(seconds + "");
seconds--;
mHandler.postDelayed(runnable,1000);
}
}
};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);
tvTimer = (TextView) findViewById(R.id.tv_timer);
mHandler = new Handler();
mHandler.postDelayed(runnable,1000);
}
}
//and also removCallback onDestroy too.
First, I used animation to hide and show TextView. I saw that using animation costing memory. So I used another way:
SetVisibility(VISIBLE) and SetVisibility(INVISIBLE) with TaskTimer
it works well and it performs better considering the memory.
The main issue is that after a restarting the timer for many times, the TextView disappear.
I need to restart the app to get it back again!
this is the code snippet:
myTimerForAnimation = new Timer();
myTimerForAnimation.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() // run on ui thread
{
public void run() {
counter++;
if (counter < 7) {
if (counter % 2 == 1) {
list_textView[x].setVisibility(View.INVISIBLE);
} else {
list_textView[x].setVisibility(View.VISIBLE);
}
} else {
myTimerForAnimation.cancel();
myTimerForAnimation.purge();
list_textView[x].setVisibility(View.VISIBLE);
}
}
});
}
}, 1000, 600);
Dont use Timer use handler,something like this:
// init the runnables
// the runnable should be members
Handler hanlder = new Handler();//If you arent on the UI thread pass a correct looper
for (int i=1; i<7 ; i++){
long delay = i * 1000;
if (i%2==0)
{
handler.postDelayed(mVisibleRunnable,delay);
}else{
handler.postDelayed(mInVisibleRunnable,delay);
}
}
Whereas the get runnablebs should be memebers because if u choose to cancel the callbacks then call
handler.removeCallbacks(runnable);
Play with it. It should fix your issue.
thanks to #EE66 for the loop idea, I used this code to solve my problem:
private void animateView(final View view){
for (int counter = 0; counter < 7; counter++) {
long delay = counter * 1000;
if (counter % 2 == 0) {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.VISIBLE);
}
;
}, delay);
} else {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.INVISIBLE);
}
;
}, delay);
}
}
}
I have an image view. So in the image view i want to change the images after a certain time period. Images are coming from an array list. Now when the no of images are 3 or more than 3, it is working perfect. But when it is 2, my logic is not working. Second image is visible for a moment and then again changed to first image here is my code:
r = new Runnable(){
int i = 0;
public void run(){
iv.setImageBitmap(alBmps.get(i));
i++;
if(i >= alBmps.size()){
i = 0;
}
iv.postDelayed(r, 5000); //set to go off again in 5 seconds.
}
};
iv.postDelayed(r, 1000);
Can any one help me what changes i need on the above code?
Thanks.
Try this
declare variables
static int i=0;
private Timer myTimer;
in your onCreate or on button click where you want to call and start the methods
myTimer = new Timer();
myTimer.schedule(new TimerTask()
{
#Override
public void run()
{
TimerMethod();
}
}, 500, 5000);
add these methods to your class
private void TimerMethod()
{
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable()
{
public void run()
{
if(i<alBmps.size())
{
iv.setImageBitmap(alBmps.get(i));
}
else
{
i=0;
iv.setImageBitmap(alBmps.get(i));
}
i++;
}
};
I have a timer in android to countdown to a future date, but it is not refreshing. Any help appreciated. my code is posted below:
public class Activity1 extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView t = (TextView)findViewById(R.id.countdown);
t.setText(timeDif());
I believe that t.setText just needs to be constantly updated, but am unsure of how to do that.
}
public String timeDif()
{
GregorianCalendar then = new GregorianCalendar(2012, 07, 21, 6, 0, 0);
Calendar now = Calendar.getInstance();
long arriveMilli = then.getTimeInMillis();
long nowMilli = now.getTimeInMillis();
long diff = arriveMilli - nowMilli;
int seconds = (int) (diff / 1000);
int minutes = seconds / 60;
seconds %= 60;
int hours = minutes / 60;
minutes %= 60;
int days = hours / 24;
hours %= 24;
String time = days + ":" +zero(hours)+":"+zero(minutes)+":"+zero(seconds);
return time;
}
private int zero(int hours) {
// TODO Auto-generated method stub
return 0;
}
}
The textbox wont update unless you do it in its own thread. The Timer runs on a different thread than the UI. Here is how I did it.
myTimer = new Timer();
myTimerTask = new TimerTask() {
#Override
public void run() {
TimerMethod();
}
};
myTimer.schedule(myTimerTask, 0, 100);
private void TimerMethod()
{
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
if (isPaused != true) {
this.tmrMilliSeconds--;
this.runOnUiThread(Timer_Tick);
}
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//This method runs in the same thread as the UI.
if (tmrSeconds > 0) {
if (tmrMilliSeconds <= 0) {
tmrSeconds--;
tmrMilliSeconds = 9;
}
} else {
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(1000);
myTimer.cancel();
tmrSeconds = setTime;
tmrMilliSeconds = 0;
isPaused = true;
}
//Do something to the UI thread here
timerText.setText(String.format("%03d.%d", tmrSeconds, tmrMilliSeconds));
}
};
That is part of the code for a count down clock I made for an ap. It demonstrates how to have one thread run (The public void run()) part, and then another part that runs on the UI thread. Hope that helps.
You shouldn't be doing this with a timer. A timer uses a thread and you don't need one (and it complicates things unnecessarily). You need to use a Runable and Handler's postDelayed method to do it. It is easier and lighter weight.
Handler mHandler = new Handler();
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
//update here
mHandler.postDelayed(mUpdateTimeTask, 100);
}
};
private void startTimer()
{
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
So I have a TextSwitcher that I want to update every second with the number of seconds it has been since the activity opened. Here is my code
public class SecondActivity extends Activity implements ViewFactory
{
private TextSwitcher counter;
private Timer secondCounter;
int elapsedTime = 0;
#Override
public void onCreate(Bundle savedInstanceState)
{
// Create the layout
super.onCreate(savedInstanceState);
setContentView(R.layout.event);
// Timer that keeps track of elapsed time
counter = (TextSwitcher) findViewById(R.id.timeswitcher);
Animation in = AnimationUtils.loadAnimation(this,
android.R.anim.fade_in);
Animation out = AnimationUtils.loadAnimation(this,
android.R.anim.fade_out);
counter.setFactory(this);
counter.setInAnimation(in);
counter.setOutAnimation(out);
secondCounter = new Timer();
secondCounter.schedule(new TimerUpdate(), 0, 1000);
}
/**
* Updates the clock timer every second
*/
public void updateClock()
{
//Update time
elapsedTime++;
int hours = elapsedTime/360;
int minutes = elapsedTime/60;
int seconds = elapsedTime%60;
// Format the string based on the number of hours, minutes and seconds
String time = "";
if (!hours >= 10)
{
time += "0";
}
time += hours + ":";
if (!minutes >= 10)
{
time += "0";
}
time += minutes + ":";
if (!seconds >= 10)
{
time += "0";
}
time += seconds;
// Set the text to the textview
counter.setText(time);
}
private class TimerUpdate extends TimerTask
{
#Override
public void run()
{
updateClock();
}
}
#Override
public View makeView()
{
Log.d("MakeView");
TextView t = new TextView(this);
t.setTextSize(40);
return t;
}
}
So basically, I have a Timer that every second adds another second and them formats the way I want to be displayed and set the text of the TextSwitcher, which I thought called makeView, but makeView only gets called once and the time stays as 00:00:01. Did I miss a step, I dont think this UI object is very well documented.
Thanks, Jake
You can only update the UI in the UI thread. So in your example you could do something like this.
private Handler mHandler = new Handler() {
void handleMessage(Message msg) {
switch(msg.what) {
CASE UPDATE_TIME:
// set text to whatever, value can be put in the Message
}
}
}
And call
mHandler.sendMessage(msg);
in the run() method of the TimerTask.
This is a solution to your current issue but there is probably a better way to do it without using TimerTasks.