Use AsyncTask Except Downloading - android

Wherever I've seen use of asynctask , it is used for downloading or operation that returns some results. But What if i just want to set a time to time updation of my TextView in activity and do some work at the end .
But at the same time How can i cancel asynctask operation from activity so its onPostExecute , do not run .Like when back button is pressed from activity. Any clues ?
[UPDATE]
For Time to time updation i mean:
TextView tv = findViewById(R.id.disco);
try{
for(int i=0;i<10000;i++){
Thread.sleep();
tv.setText(" "+i);
}
}
catch(Exception e){}
/* i know i can achieve finally in onPostExecute but what if i want to cancel it during runtime*/
finally{
// do some more operations after execution
}

Done it myself after some brain storming and searching , i am using CountDownTimer.
in OnCreate():
counter = new CountDownTimer((PROGRESSSECONDS+1)*1000,1000) {
int collapsed = 0;
#Override
public void onTick(long millisUntilFinished) {
collapsed++;
pb.setProgress(collapsed);
}
#Override
public void onFinish() {
Intent in = new Intent(FirstActivity.this,PointsDrawerActivity.class);
startActivity(in);
}
};
counter.start();
in onBackPressed():
#Override
public void onBackPressed() {
counter.cancel();
counter = null;
setContentView(R.layout.activity_first);
}
it worked.

Handler is optimum for your requirement
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
callMethod();
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
and in order to cancel an ongoing AsyncTask the official docs says it all
A task can be cancelled at any time by invoking cancel(boolean).
Invoking this method will cause subsequent calls to isCancelled() to
return true.
After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[])
returns.
To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically
from doInBackground(Object[]), if possible (inside a loop for
instance.)
Ex: MyTask.cancel(true);

You should use timer task rather than Async task here.
Here is sample:
private TimerTask timerTask;
int i = 0;
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//Do your text view update here.
tv.setText(" "+ (i++));
}
});
}
};
In your onResume() do like:
private Timer timer;
public void onResume() {
timer = new Timer();
timer.schedule(timerTask, 1000); // time in milliseconds, you can set accordingly requirement.
}
And onPause() you can stop it by:
public void onPause() {
if (timer != null) {
timer.cancel();
timer = null;
}
}

Related

How to update a textview frequently with a spesific time delay?

I need to update a TextView frequently with a specific time delay in the android studio. The code is below. Thank you.
Edit: I also need to end the loop with a button click or with an "if" control.
//INFLATION CALCULATION !!!
/**
* This method calculates Inflation value.
*/
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
}
}, delay*12);
}
Call the same method inside the runnable in order to keep the loop going
Use a flag in order to be able to stop the loop: shouldCalculate
private boolean shouldCalculate = true; // set to false when you want to end the loop
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (shouldCalculate) {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
calculateInflation();
}
}
}, delay*12);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
customHandler.postDelayed(this, 0);
}
};
public void startTimer() {
//timer
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public void stopTimer() {
//timer stops
customHandler.removeCallbacks(updateTimerThread);
//timer ends
}
make a reference of runnable thread , start it using startTimer() and remove thread using stopTimer() as you said on a button click or up on a specific conditions .Also you can change the postDelayed milliseconds as ur wish
Try below code. This will do the trick. If you find any problem please let me know.
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
if(shouldRepeat)
calculateInflation();
}
}, delay*12);
}
And second approach can be CountDownTimer. Make a method as shown in below code
public void timerTask(final int loopTime){
//Loop time is the actual time for repeatation
new CountDownTimer(loopTime, 1000) {
public void onTick(long millisUntilFinished) {
//this tells you one second is passed
}
public void onFinish() {
//here on time finish you need to define your task
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
//call the same method again for looping
timerTask(loopTime);
}
}.start();
}
Simplest way. Here updateRunnable calls itself with delay. Make updateRunnable as global variable to access from anywhere.
Runnable updateRunnable = new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
handler.postDelayed(this, UPDATE_TIME);
}
};
Start handler. Here we start handler immediately without delay.
handler.postDelayed(updateRunnable, 0)
Stop handler
handler.removeCallbacks(updateRunnable)
By the way don't forget to stop handler on onDestroy()

Android Button click Handler

I have a button(in say Activity 1), which when clicked should start a service (eg Service 1). But there must be a delay of 5 seconds before the service starts. I achieved this using SystemClock.sleep(5000) in the onStartCommand of the service. This worked properly.
Now I want to add the functionality that if the button is clicked again(even before the 5 seconds end), the service WILL NOT BE STARTED.
Any ideas how to do this?
(Edit : Please read the entire question before marking it as a duplicate. Thanks)
You can use handler with post delayed to achieve your goal. Make your button disable and enable it after five seconds along with starting your service. You can implement the following code:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
button.setEnabled(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//start your service here
button.setEnabled(true);
}
}, 5000);
}
});
Above code will disable your button for 5 second and will start your service after 5 second.
I'd use a util class similar to the following. Pass it in a runnable and a delay in ms and you can call stop() on it to cancel before it has run. You can also call restart() if you want to restart your timer. I use it for things like auto showing/hiding controls on an immersive view.
public class DelayableRunnable{
int mDelay = 0;
Handler mHandler = new Handler();
Runnable mRunnable;
boolean mIsRunning = false;
public DelayableRunnable(Runnable runnable, int delay){
mRunnable = runnable;
mDelay = delay;
}
public void setNewDelay(int delay){
mDelay = delay;
}
public void start(){
if(mIsRunning) {
stop();
}
mHandler.postDelayed(mRunnable, mDelay);
mIsRunning = true;
}
public void stop(){
mHandler.removeCallbacks(mRunnable);
mIsRunning = false;
}
public void restart(){
stop();
start();
}
}
You can use Handler.postDelayed function for delayed actions in Android enviroment (better than plan java methods)
final Handler handler = new Handler(); // or use existed one your_view.getHandler()
handler.postDelayed(new Runnable() {
#Override
public void run() {
//start your service
}
}, 5000 /* 5s * 1000ms */);
Or simpler use you view function (work same as above):
your_view.postDelayed(new Runnable() {
#Override
public void run() {
//start your service
}
}, 5000 /* 5s * 1000ms */);
A facility for threads to schedule tasks for future execution in a background thread. Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals void schedule (TimerTask task,long delay) Schedules the specified task for execution after the specified delay.
new Timer().schedule(new TimerTask() {
#Override
public void run() {
alertDialog.dismiss();
startActivity(new Intent(****.this,*********.class));
}
},5000);

Android Timer update UI between multiple tasks

I have tried multiple ways to have a single persistent timer update the ui in multiple activities, and nothing seems to work. I have tried an AsyncTask, a Handler, and a CountDownTimer. The code below does not execute the first Log.i statement.... Is there a better way to start the timer (which must be called from another class) in Main (which is the only persistent class)?
public static void MainLawTimer()
{
MainActivity.lawTimer = new CountDownTimer(MainActivity.timeLeft, 1000)
{
public void onTick(long millisUntilFinished)
{
Log.i("aaa","Timer running. Time left: "+MainActivity.timeLeft);
MainActivity.timeLeft--;
if(MainActivity.timeLeft<=0)
{
//do stuff
}
else
{
//call method in another class
}
}
public void onFinish()
{ }
}.start();
}
To clarify my problem:
When I run the code the Log.i("aaa","Timer running") statement is never shown in the log, and the CountDownTimer never seems to start. MainLawTimer is called from another class only (not within the same class.
For CountDownTimer
http://developer.android.com/reference/android/os/CountDownTimer.html
You can use a Handler
Handler m_handler;
Runnable m_handlerTask ;
int timeleft=100;
m_handler = new Handler();
#Override
public void run() {
if(timeleft>=0)
{
// do stuff
Log.i("timeleft",""+timeleft);
timeleft--;
}
else
{
m_handler.removeCallbacks(m_handlerTask); // cancel run
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
Timer
int timeleft=100;
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
Log.i("timeleft",""+timeleft);
//update ui
}
});
if(timeleft>==0)
{
timeleft--;
}
else
{
_t.cancel();
}
}
}, 1000, 1000 );
You can use a AsyncTask or a Timer or a CountDownTimer.
Thank you all for your help, I discovered the error in my code... timeLeft was in seconds rather then milliseconds. Since timeLeft was under 1000 (the wait period) the timer never started.

Timer Not Stopping In Android

THE PROBLEM
I am having problems stopping the Timer whilst developing in android.
The timer is already null when it comes to stopping it.
I then move the timer initialisation to outside of a method just like the TimerTask which solves the null problem but still doesn't cancel when timer.cancel(); is called upon it.
The code below is an example of the timer already being null when it comes to stopping the recording.
TimerTask
My TimerTask is initialized inside the class but outside of a method and the codes below...
private TimerTask task = new TimerTask() {
#Override
public void run() {
Log.e("TRACK_RECORDING_SERVICE","Timer Running");
}
};
Timer & Timer Start
I then have a startRecroding method which is called when I want to start the timer...
public void startRecording(){
timer = new Timer("Message Timer");
timer.scheduleAtFixedRate(this.task, 0, 1000);
}
Timer Stop
I then call the below method when I want to stop the timer...
public void stopRecording() {
if (timer != null) {
timer.cancel();
timer = null;
} else {
Log.e("TRACK_RECORDING_SERVICE","Timer already null.");
}
}
Any help would be much appreciated.
timer = new Timer("Message Timer");
Here your object timer is not a static so timer.cancel(); will cancel another instance of the Timer class. I suggest you to create a static instance variable of Timer Class on the top of the class, like below,
private static Timer timer;
in the run() method, check if timer is null then
private TimerTask task = new TimerTask() {
#Override
public void run() {
if (timer == null)
cancel();
...
}
cancel the operation.
Ok so the problem was in the instantiation not the actual stopping of the timer.
Everytime I called:
timer = Timer()
timer!!.scheduleAtFixedRate(object : TimerTask() {
override fun run() {
//something
}
}, delay, period)
It created another instance so the old instance was still running somewhere with no way to stop it.
So I just made sure to instantiate it when the timer is null so that no previous instance is getting pushed around and still running on the background.
if(timer == null) {
timer = Timer()
timer!!.scheduleAtFixedRate(object : TimerTask() {
override fun run() {
// something
}
}, delay, period)
}
Then just cancel it and set it to null.
fun stopTimer() {
if (timer != null) {
timer!!.cancel()
timer!!.purge()
timer = null
}
}
if(waitTimer != null) {
waitTimer.cancel();
waitTimer.purge()
waitTimer = null;
}
I know it's late but I also encountered this issue in my project, and hope my solution may give people some ideas. What I did in my project is as below:
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
//TODO Update UI
}
};
public void stopTimer() {
if (timer != null) {
handler.removeCallbacks(runnable);
timer.cancel();
timer.purge();
timer = null;
}
}
public startTimer() {
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
handler.post(runnable);
}
}, 0, 100);
}
I think what's missed in previous answers is removeCallbacks.
Try this example....
TimerTask mTimerTask;
final Handler handler = new Handler();
Timer t = new Timer();
int nCounter = 0;
//function for start timer
public void doTimerTask()
{
mTimerTask = new TimerTask()
{
public void run()
{
handler.post(new Runnable()
{
public void run()
{
nCounter++:
//your code
.....
......
}
});
}};
// public void schedule (TimerTask task, long delay, long period)
t.schedule(mTimerTask,0,50); //
}
//function for stop timer
public void stopTimerTask(){
if(mTimerTask!=null){
Log.d("TIMER", "timer canceled");
mTimerTask.cancel();
nCounter = 0;
}
}
//use above two function for start and stop timer.
Just in case if someone still comes here to find a solution to this problem, here is my experience.
I am running a timer in a service.
startForegroundService(mServiceIntent);
timer = new Timer();
When you refresh a service, you don't necessarily cancel it first, you just call startForegroundService(mServiceIntent); again.
If you don't cancel the timer before you refresh the service, the original timer is still running in the background and calling methods even though you stop the timer in the refreshed new service.
So to sum it up, stop your timer before you refresh or update a background task.
I hope it helps someone.
Though this is an old question, I've figured out an easy solution.
var timeTaskInstance : TimerTask ?= null
val task: TimerTask = object : TimerTask() {
override fun run() {
timeTaskInstance = this
Log.e("TRACK_RECORDING_SERVICE", "Timer Running")
}
}
Now cancel timer from anywhere:
timeTaskInstance?.cancel()
I think you've canceled another instance of the timer.
Your timer task would be better handled by a helper class.
public class TimerHelper {
Timer timer;
long InitialInMillis = 10 * 1000;
long DelayInMillis = 2 * 60 * 1000; // 2 minutes
public TimerHelper() {
timer = new Timer();
timer.schedule(new MyTimerTask(), InitialInMillis, DelayInMillis);
}
public void stopTimer() {
if(timer != null){
timer.cancel();
}
}
class MyTimerTask extends TimerTask {
#Override
public void run() {
// your task will be run every 2 minutes
yourTask();
}
}
}

Android Timer thread which exits on a "is true" condition

I'm writing an Android application and I need a Timer to be set which will execute a method every one second and then stop once a boolean variable (set by aforementioned method) becomes true.
Here's an overview of what I'm trying to do:
boolean done = false;
public void someMethod() {
if(done == false) {
myTimer = new Timer(); //Set up a timer, to execute TimerMethod repeatedly
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
}
if(done == true) {
//TimerMethod will eventually set 'done' to true. When this happen, do layout modifying stuff here. Causes error as non-UI thread is executing the layout modifying stuff. Do I spawn a new UI thread here to do it? If so, how? :/
}
}
TimerMethod() {
String result = someServerMethod();
if(result == "theResultWeWant") {
myTimer.cancel(); //stop the timer - we're done!
done = true; //set 'done' to true so the line of code in someMethod() will now run
someMethod();
}
}
Edit: I've updated the code above to reflect what I'd like to do. I'm hoping I can get the done flash to be set to true and then carry on executing someMethod but I'm sure it's not that simple! Do I perhaps need to spawn a new thread from TimerMethod() to execute the code from the done == true line?
All UI interactions need to be done from the main(UI) thread. In your case, you were calling someMethod() from your TimerTask which is a seperate thread. A handler is used to interact with your main thread from a helper thread.
public void someMethod() {
myTimer = new Timer(); //Set up a timer, to execute TimerMethod repeatedly
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
}
}
TimerMethod() {
String result = someServerMethod();
if(result.equals("theResultWeWant")) {
myTimer.cancel(); //stop the timer - we're done!
mHandler.sendEmptyMessage(0): //send message to handler to update UI
}
}
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
doUIMethod();
}
};

Categories

Resources