Can you tell me where is the problem on this line: timerText.setText(seconds);.
public class ShowTimer extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.timer_test_xml);
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
int seconds;
TextView timerText = (TextView) findViewById(R.id.TimerTestId);
#Override
public void run() {
seconds++;
timerText.setText(seconds);
}
}, 0, 1000);
}}
I think what you want to do is display seconds in the text view. However, the TextView.setText(int) function does not do this (Im not actually sure what it does). What you want to do is timerText.setText(""+seconds); to convert the parameter into a string and change the function call to a different overloaded function.
seconds is an int, whereas I think you want to be passing as character sequence, or a reference to one via a resource id, as per the documentation.
Though this doesn't answer the OP's original question, there are alternative (and - if you agree with the recommendations from the Android docs - better) ways to do this described in this thread.
As with Richard's suggestion, your other problem is updating the TextView on the non-UI thread, so consider using a Handler.
Example
public class ShowTimer extends Activity {
private Handler mHandler;
private TextView timerText = null;
private int seconds;
private Runnable timerRunnable = new Runnable() {
#Override
public void run() {
timerText.setText(String.valueOf(seconds++));
mHandler.postDelayed(timerRunnable, 1000);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timer_test_xml);
mHandler = new Handler();
timerText = (TextView) findViewById(R.id.TimerTestId);
timerRunnable.run();
}
}
Related
Consider an application, it will count down from 60 to 0 at intervals of 1 second.
public class MainActivity extends AppCompatActivity {
int time;
TextView timeDisplay;
private Handler handler new Handler();
#Override
protected void onCreate(Bundle savedinstanceState) {
super.onCreate(savedinstanceState);
setContentView(R.layout.activity_main);
time = 60;
timeDisplay (TextView) findViewByid(R.id.timeDisplay);
handler.removeCallbacks(updateTimer);
handler.postDelayed(updateTimer, 1000);
}
private Runnable updateTimer = new Runnable(){
public void run(){
// somthing here
}
};
}
I try to implement a count down timer like this but I am very new to android studio and java and did not really know how to implement this. Hence any comment will be very useful. Thank you.
Did you tried CountDownTimer? You could read more information here
CountDownTimer
I have the following code. My problem is, that I can't get the JSON.execute() to stop/cancel. I spend quite some time looking up possible answers but I wasn't able to find anything that really worked (e.g. JSON.cancel(true)). As soon as I turn the trackerswitch on, the AsnycTask starts running every 3 seconds just like it's supposed to. Is there a way to easily stop the AsyncTask from executing as soon as the trackerswitch is turned off?
private boolean tracking = false;
private Switch trackerswitch;
private final Timer timer= new Timer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.table_layout);
final Handler handler=new Handler();
final int delay = 4000;
trackerswitch=findViewById(R.id.trackerswitch);
trackerswitch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NetworkAccess JSON = new NetworkAccess();
if(trackerswitch.isChecked()){
trackerswitch.setText("Tracking...");
tracking=true;
handler.postDelayed(new Runnable() {
#Override
public void run() {
NetworkAccess JSON = new NetworkAccess();
JSON.execute();
handler.postDelayed(this, delay);
}
},delay);
}
else{
tracking=false;
trackerswitch.setText("Start Tracking");
}
}
});
}
}
This is what's called in the network class:
public class NetworkAccess extends AsyncTask<Void, Void, Void> {
public ArrayList<String> alldata = new ArrayList<>();
public ArrayList<String> locationlist = new ArrayList<>();
int stride;
String data;
#Override
protected Void doInBackground(Void... voids) {//4B4ADC
SOME CODE WHICH ISN'T IMPORTANT FOR MY PROBLEM
alldata.addAll(elementlist);
locationlist.addAll(loctrack);
}
}
catch(IOException | JSONException e){
MainActivity.field1.setText(e.getClass().getCanonicalName());
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
MainActivity.field1.setText(String.format("%20s %20s", alldata.get(0), alldata.get(1)));
COUPLE MORE OF THESE SETTEXT COMMANDS TO FILL A TABLE WITH DATA
}
}
Thanks for your help!
handler.postDelayed() adds objects of the Runnable you provide to the message queue, to be run at the specified interval. You need to remove all the queued objects from the message queue in order to cancel the execution. Calling JSON.cancel(true) does not affect other objects that are already added to the queue.
You'll have to retain a reference to your Runnable implementation and then call handler.removeCallbacks(r) to prevent further executions. Instead of using an anonymous class in handler.postDelayed().
This documentation page sheds more light on the matter.
Also refer this page for what happens when you call cancel(true) on an AsyncTask.
I tried this code (seen below) and it says "Cannot resolve symbol 'customHandler'", I am a beginner so I don't know yet how to fix this problem.
It would be awesome, if you could explain me how to fix it.
I am thankfull for every help :D
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
android.os.Handler customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
//write here whatever you want to repeat
customHandler.postDelayed(this, 1000);
}
};
I am trying to make a method run from the begining once every minute.
customHandler is a local variable in your method onCreate, so method run() cannot see it.
Make customHandler a member variable of your class to fix.
//Member variable
android.os.Handler customHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Assign value
customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable() {
public void run()
{
//USE the value
customHandler.postDelayed(this, 1000);
}
};
Your customHandler object is not visible from your updateTimerThread.
Try to change the visibility of this variable by moving it outside of your method.
Here is an exemple:
android.os.Handler customHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
//write here whatever you want to repeat
customHandler.postDelayed(this, 1000);
}
};
But using a Timer and a TimerTask may be a better solution than recursively calling postDelay on your handler.
It's makes cleaner code and it assure you that it will be runned at a specific frequency (for example every minutes) whereas your solution only allows to fix the delay between the end of a run and the beginning of the next one (if it take 30s to run and delay is 1 minute, it will run every 1.5mn)
// declare your timer
Timer basicTimer;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
// create a Timer
basicTimer = new Timer();
// create the periodic task, here it's an anonymous class
TimerTask updateTimerThread = new TimerTask() {
public void run() {
//write here whatever you want to repeat
// no need to call postDelayed
}
};
// schedule the task to run every minutes
basicTimer.scheduleAtFixedRate(updateTimerThread, 0, 60*1000); // 1minutes = 60000 ms
}
Ok - I know there has got to be a simple solution to this but for the life of me I can't figure it out.
Programming a very basic android activity to simply iterate through 0-99. I have a textview that I want to display the count. What happens is that it simply stays blank until the end and then shows the ending count (99).
Not sure if a textview is the right way to display or what the answer is. Any help is greatly appreciated. Thanks in advance
Try using code like this in onCreate (where number is defined as a field):
textView.post(new Runnable() {
#Override
public void run() {
number++;
textView.setText("counting: " + number);
if (number < 100) {
textView.postDelayed(this, 50);
}
}
});
Edit: code was edited as View classes have post and postDelayed, which propagates call to Handler instance they have internally.
You need to read a bit about Handler class.
Warning: this code leaks Activity for the time of approximatelly 5 seconds and should not be used directly in production code. You need to remove Runnable from the message queue at the appropriate time (maybe in onDestroy, but it depends on your needs).
View.removeCallbacks for anti-memory-leak.
My guess is that your onCreate() has code like this:
for (int i=0;i<100;i++) {
tv.setText(String.valueOf(i));
Thread.sleep(100); // or something to delay for a bit
}
That will give you the output that you are describing.
As with many GUI frameworks, Android's UI is event-driven. Calling setText() does not update the screen. Rather, it puts a message on a queue, asking for the screen to be updated. That queue is processed by the main application thread... the same thread that is calling onCreate() in the first place. Hence, what you are doing is queuing up 100 setText() calls, none of which will be processed until your loop is complete. Applying the 100 of them takes very little time, giving the visual result of only seeing the last change.
User a timer scheduled at a fixed rate. Increment a counter every second. Set the text on the UI thread. cancel the timer when required.
public class MainActivity extends Activity {
TextView _tv;
Timer _t;
int _count=0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_tv = (TextView) findViewById( R.id.textView1 );
_t = new Timer();
_tv.setText(""+_count);
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
_count++;
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
_tv.setText(""+_count);
if(_count==99)
{
_t.cancel();
}
}
});
}
}, 1000, 1000 );
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
_t.cancel();
}
}
Use a countdown timer, in below code, onTick() will get called every second, here you can display/update your number each second.
set interval according to your need. Its in mili seconds.
public class TimerActivity extends Activity {
private final long startTime = 100 * 1000;
private final long interval = 1 * 1000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
countDownTimer = new MyCountDownTimer(startTime, interval);
countDownTimer.start();
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
text.setText("Time's up!");
}
#Override
public void onTick(long millisUntilFinished) {
text.setText(100 - millisUntilFinished/1000);
}
}
}
I have the following code that responds to a button click, changes the view and then after 5 seconds switches the view back:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
Button test = (Button)findViewById(R.id.browseLocation);
test.setOnClickListener(testListener);
}
private TimerTask revert = new TimerTask(){
#Override
public void run() {
setContentView(R.layout.menu);
}
};
private OnClickListener testListener = new OnClickListener() {
public void onClick(View v) {
setContentView(R.layout.test);
Timer tim = new Timer();
tim.schedule(revert, 5000);
}
};
However this code does not work. The run method of the timetask is hit but setContentView fails. I assume it has something to do with scope inside the timetask.
How can I achieve the desired result?
Try yourActivityName.this.setContentView(). Do you know if revert is being called at all (i.e. using Logging)?
Found on another post that setContentView cannot be called from a non-UI thread.
Can achieve the desired affect using runOnUiThread, but not recommended.