In my app (as long as it is open) I want to sync my data with my server.
My strategy is the following :
//create the handler on which we will use postdelayed
Handler handler = new Handler();
//create the first runnable.
//Will this run on UI thread at this stage ? as it is being called from the handler ?
Runnable runnable1 = new Runnable()
{
public void run()
{
Thread t = new Thread(runnable2);
}
};
//create the second runnable.
//This is for sure being called from a thread, so it will not run on UI thread ? NO ?
Runnable runnable2 = new Runnable()
{
public void run()
{
//connect to internet
//make the check periodical
handler.postdelayed(runnable1, 1000);
}
};
//call the postdelayed.
handler.postdelayed(runnable1, 1000);
In case I want the handler to stop its runnable task once the application is closed. What shall I do incase I have several activities and I do not know where is the user when he/clicks the home button. Should I include a check in all onDestroys() ?
Yes you're second Runnable will be ran on a new thread not the UI thread.
When you do new Handler(); this creates a handle to the current thread, if this code was in onCreate that thread would be the UI thread.
Therefore when you do handler.post it will post onto the UI thread (runnable1) , but when you start runnable2 you are explicitly creating a new thread to run this on.
It might not be the right strategy to create a new thread every 1 second (postDelayed ..1000) perhaps keep a reference to another background thread and post it a message every second to do something new.
To stop your repeated runnables you need to call removeCallbacks(runnable1) in onPause of any Activity (that I assume called postDelayed in onCreate)
Related
I'm design an app that keep sending JSON data to a server after t seconds and updating web view whenever it get an response from that server (after sending success). I want this background job running forever until i quit the app. Should i use loop inside an async task ?
I read in android main page that Async Task should be use as a one-time only job.
Use Runnable and Handler Class to execute a function with post delayed
Handler handler = new Handler();
final int delay = 5000; //milliseconds
Runnable r=new Runnable(){
public void run(){
//Execute your asynctask here
}
};
handler.postDelayed(r, delay);
And update the UI in onPostExecute of Asynctask
I'm wondering when should I use handler.post(runnable); and when should I use
new Thread(runnable).start();
It is mentioned in developers documentation for Handler:
Causes the Runnable r to be added to the message queue. The runnable
will be run on the thread to which this handler is attached.
Does this mean if I write in the onCreate() of Activity class:
Handler handler = new Handler();
handler.post(runnable);
then runnable will be called in a separate thread or in the Activity's thread?
You should use Handler.post() whenever you want to do operations on the UI thread.
So let's say you want to change a TextView's text in the callback. Because the callback is not running on the UI thread, you should use Handler.post().
In Android, as in many other UI frameworks, UI elements (widgets) can be only modified from UI thread.
Also note that the terms "UI thread" and "main thread" are often used interchangeably.
Edit: an example of the long-running task:
mHandler = new Handler();
new Thread(new Runnable() {
#Override
public void run () {
// Perform long-running task here
// (like audio buffering).
// You may want to update a progress
// bar every second, so use a handler:
mHandler.post(new Runnable() {
#Override
public void run () {
// make operation on the UI - for example
// on a progress bar.
}
});
}
}).start();
Of course, if the task you want to perform is really long and there is a risk that user might switch to some another app in the meantime, you should consider using a Service.
To answer you specific question:
Does this mean if in the onCreate of Activity class I write:
Handler handler = new Handler() hanlder.post(runnable); then, runnable
will be called in a separate thread or on the Activity's thread?
No it won't be. The Runnable will be called on the Main Thread itself.
Handler is simply used for posting a message to the thread to which it is attached (where its is created).
It does not create a thread on its own.
In your example, you created a Handler in the main Thread (that where Activity.OnCreate() is called) and hence any message posted on such a Handler will be run on the Main Thread only.
Example is jacked:
mHandler = new Handler();
new Thread(new Runnable(){
#Override
public void run () {
mHandler.post(new Runnable() {
#Override
public void run () {
mUiView.setX(x);
}
});
}
}).start();
Alternatively you can skip the handler and use the post method on the view directly:
new Thread(new Runnable(){
#Override
public void run () {
mUiView.post(new Runnable() {
#Override
public void run () {
mUiView.setX(x);
}
});
}
}).start();
This is a good post that outlines the difference: What exactly does the post method do?
use handler.post() when you want to post the code (usually from background thread) to the main thread. Yea, POST,just like you, post a letter to someone. With the help of handler the code will be executed ASAP i.e. almost immediately.
I have written a handler that calls the method every time interval. I want to remove that handler in on destroy(). The code i use as follows, In Oncreate()
private final Handler _handler = new Handler();
public int DATA_INTERVAL = 30 * 1000;
Runnable getData;
getData = new Runnable()
{
#Override
public void run()
{
recieveData();
}
};
_handler.postDelayed(getData, DATA_INTERVAL);
and in ondestroy(), i use,
_handler.removeCallbacks(getData);
But removecallbacks not work. It calls after exiting the activity.
removeCallbacks(Runnable r):
Remove any pending posts of Runnable r that are in the message queue.
so removeCallbacks(..) only stops pending messages (Runnables) not currently running runnable so if you want to stop currently running Runable then use a Boolean varaible for Stoping Thread when user Exit from your app.
see this post for removeCallbacks not stopping runnable
You are not showing the most important part of the code which is the receiveData method. As you said you are running the task periodically, you must be calling again postDelayed from inside that method to reschedule the task. Probably background threads involved as you cannot do networking on the main thread.
You most likely have a race condition when exiting the Activity. onDestroy runs first and then the task is posted again.
You should use
handler.removeCallbacksAndMessages(null);
Then all handler callbacks will removed.
I am attempting to making a method that on a button click, it will display a layout.
After a few seconds, I want a new activity/layout to be displayed.
Any suggestions on how to do this??
I would suggest not to wait on the UI Thread.
You can use a Handler for your Task. The run method will be executed in the same thread the Handler has been created:
//delay in ms
int DELAY = 1000;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(CurrentActivity.this, NextActivity.class);
startActivity(intent);
}
}, DELAY);
Does the UI need to do anything during this delay? If not, you can just use:
Thread.sleep(timeToWaitInMilliseconds);
inside your handler for the button. This will stop the UI thread for a few seconds however, your UI will "Freeze" during the delay.
A slightly better option is to use an AsyncTask and a Handler, which is a new thread, and make that thread sleep for the time you want to delay the new activity opening then opening the new activity in the handler.
The asynctask is a bit better for your case I think, as it will allow the user to interact with the UI during your "delay".
More info on AsyncTasks here:
http://developer.android.com/reference/android/os/AsyncTask.html
I have a time consuming task (iterating through files and sending it's content to server) that I want to execute in background thread, in specific interwal (that's why I want to use Handler).
From UI thread I have a call like this:
LogsManager lm;
lm = new LogsManager(this);
lm.processLogFiles();
And in LogsManager class I have following piece of code:
public void processLogFiles(){
Handler mHandler = new Handler();
mHandler.postDelayed(logsRunable, 1000);
}
private Runnable logsRunable = new Runnable() {
#Override
public void run() {
File f = new File(Environment.getExternalStorageDirectory()+Constants.LOG_DIR);
File[] logFiles = f.listFiles();
for (int i = 0; i < logFiles.length; i++) {
readLogs(logFiles[i]); // executes some other methods inside
}
}
};
As you can see it's just method with Handler that calls Runnable. And, unfortunately it also blocks my UI thread. Isn't Handler supposed to start a new thread for Runnable? I use handlers in other parts of my app also, and they works just fine. Am I'm doing something wrong?
As stated in the docs, Handler:
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it
So if you're creating mHandler in UI thread, then it will run the tasks in UI thread - hence the problem.
All the post* methods in Handler run code on Handler's original thread (in your case the GUI thread). If you want a background thread, you need to explicitly start one (see below) or use AsyncTask, if you need to update the GUI.
Thread t = new Thread(logsRunable);
t.start();
I think you should use AsyncTask class for this purpose.
Scheduled the execution for the task after a specific delay, in your case it is 1000.
I also think AsyncTask is a good solution for your case.