I am writing an Android application where I need to periodically (every 30 seconds) fetch data from the server. I was thinking about using AlarmManager to schedule those tasks, however I need to be able to pass a callback function that updates the view. Since the Intent cannot encapsulate a callback, I decided to find another solution, which was a "worker thread". The problem here is that the request to the server is performed in AsyncTask where onPreExecute and onPostExecute have to be running from the Ui thread, so I really cannot do it this way either.
I would appreciate any suggestions what would be the best approach in this case.
Use a Handler.
Handler mHandler;
public void useHandler() {
mHandler = new Handler();
mHandler.postDelayed(mRunnable, 30000);
}
private Runnable mRunnable = new Runnable() {
#Override
public void run() {
Log.e("Handlers", "Call asynctask");
/** Call your AsyncTask here **/
mHandler.postDelayed(mRunnable, 30000);
}
};
Related
final Handler handler = new Handler();
LOG.d("delay");
handler.postDelayed(new Runnable() {
#Override public void run() {
LOG.d("notify!");
//calling some methods here
}
}, 2000);
The "delay" does shows in the log, but not others at all. And the method called in the run() is not called at all also. Can anyone help explain why this happens, am I doing anything wrong?
The class that has this code extends IntentService, will this be a problem?
============================
UPDATE:
I put this code in the class that extends IntentService. The only place I found it worked was in the constructor. But I need to put it in the onHandleIntent method. So I checked the documentation for onHandleIntent and it said:
This method is invoked on the worker thread with a request to process.Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf.
So based on the result I get, I feel like I cannot use postDelayed in "worker thread". But can anyone explain this a bit more, like why this is not working in worker thread? Thanks in advance.
Convert
final Handler handler = new Handler();
to
final Handler handler = new Handler(Looper.getMainLooper());
This worked for me.
You are using looper of the main thread. You must create a new looper and then give it to your handler.
HandlerThread handlerThread = new HandlerThread("background-thread");
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper());
handler.postDelayed(new Runnable() {
#Override public void run() {
LOG.d("notify!");
// call some methods here
// make sure to finish the thread to avoid leaking memory
handlerThread.quitSafely();
}
}, 2000);
Or you can use Thread.sleep(long millis).
try {
Thread.sleep(2000);
// call some methods here
} catch (InterruptedException e) {
e.printStackTrace();
}
If you want to stop a sleeping thread, use yourThread.interrupt();
this is how i use handler:
import android.os.Handler;
Handler handler;
//initialize handler
handler = new Handler();
//to start handler
handler.post(runnableName);
private Runnable runnableName= new Runnable() {
#Override
public void run() {
//call function, do something
handler.postDelayed(runnableName, delay);//this is the line that makes a runnable repeat itself
}
};
Handlers and Services will be predictable when the device screen is on.
If the devices goes to sleep for example the Handler will not be a viable solution.
A much more better and reliable solution will be to use:
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
IntentService is not designed for such scenario. You can use a regular Service instead. You can put the handler inside the onStartCommand(). Don't forget to
call stopSelf() on the Service instance to shut it down after the handler.postDelayed(){}
The most simple is to wait before ending onHandleIntent():
SystemClock.sleep(2000);
OK, so I know how to do a backround task, I know how to do a periodic task (using handle postdelayed and runnable), I also know how to do UI task from background thread (via handler) but I am not able to execute a periodic background task that does some action on the UI thread.
I am trying to execute some background task every minute in which I have to make a network call. After the call is over, depending on the output I have to update the UI. I tried to do something like this
private void DoTask() {
Thread thread = new Thread() {
public void run() {
Looper.prepare();
final Handler handler = new Handler();
handler.post(netRunnable);
Looper.loop();
}
};
thread.start();
}
Runnable netRunnable = new Runnable() {
#Override
public void run() {
handler.getLooper().prepare();
final Handler handler1 = new Handler(Looper.getMainLooper());
if ( do background work and check result){
handler1.post(new Runnable() {
#Override
public void run() {
//Do UI Task
}
});
}
handler.getLooper().loop();
handler.postDelayed(netRunnable, 60000);
}
}
I understand that there might be some fundamental flaws with my implementation but I do not know how to do this task properly. Right now it is giving the error that Only one Looper may be created per thread.I get what it is trying to say. But can anyone please suggest to do this the right way.
You could use Async Tasks. These are designed for it :
http://developer.android.com/reference/android/os/AsyncTask.html
It allows you to execute a network call in the background, then when you get the result, execute an action on the UI thread
Declaration :
private class MyTask extends AsyncTask<Input, Void, Output> {
protected Output doInBackground(Input... inputs) {
// do something on the network
return myOutput;// use this to transmit your result
}
protected void onPostExecute(Output result) {
// do something on UI thread with the result
}
}
If you want to repeat it, just create a runnable to launch it, and after every call, schedule the next one :
MyTask myTask;
Handler handler = new Handler();
Runnable myRunnable = new Runnable() {
#Override
public void run() {
MyTask myTask = new MyTask();
myTask.execute(myArg);
handler.postDelayed(netRunnable, 60000); // schedule next call
}
}
To launch it for the first time :
handler.postDelayed(myRunnable, 60000);
Or, if you want to launch it immediately :
handler.post(myRunnable);
Do not forget to cancel the Task when your activity is destroyed :
myTask.cancel(true);
Maybe you are better of, creating a seperate (Intent)Service and calling it periodically with postDelayed. Create a BroadcastReceiver in your Activity and handle UI changes there.
Another hint for handling UI changes from other threads: It is not possible. Therefore you need to call runOnUiThread. Here is how to use it
If activities are frequently switching, why not reversing the responsibilities. You might create a service which executes a periodic network task.
Then,
- either your activities periodically call this service to get the value.
- or you use a listener system : you create an interface that your activities must implement in order to get notified from the task completion
I have a thread where I need to periodically perform some checks, get files from the web, and send messages to the main UI thread. I even need to use UI thread parameters (like the map visible area) on each loop of the worker thread. So I suppose that i need to implement bidirectional communication between UIthread and workerThread.
Another problem is that I need to save the identifier of each marker added to the map. I want to save the result of map.addMarker inside my custom array stored in my worker thread. this means that from the uithread, where i update the map, i should tell the workerThread to update the array of markers..
This is a sample of my actual worker thread:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
#Override
public void run(){
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
My actual problem is that when the UI thread ends processing the message received from the worker thread i should perform an action on the worker thread.
I thought 2 solutions:
1)wait on the worker thread till the message has been processed by the UI thread
2)process the message on the UI thread and then send a message to the worker thread.
I don't know how to do the solution1, so i tried the solution2. I tried adding a looper to my worker thread (RUN sub), this way:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
#Override
public void run(){
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// Act on the message received from my UI thread doing my stuff
}
};
Looper.loop();
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
The problem is that after the Looper.loop() no line of code is executed. I read that this is normal. I read many articles but I didn't understand how should I allow the execution of my while loop, and simultaneously process messages coming from my UI thread.
I hope the problem is clear. Suggest me the best solution.
don't do this:
while(true){
sleep(2000);
it's awfully bad on so many levels. if you need some background processing, use AsyncTasks, if you need a repeating event, use:
private Handler mHandler = new Handler();
private Runnable mSomeTask = new Runnable() {
public void run() {
doSomething();
}
};
and then somewhere in the code:
mHandler.postDelayed(mSomeTask, 100);
this will make your program work faster, jam less resources and basically be a better Android citizen.
I realize this is a very old question, but for periodic task scheduling, use this code:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> periodicTask = scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// do some magic stuff here
// note however, that you're running in background!
Log.d("PeriodicTask", "Doing something....");
}
}, 0 /* initial delay */, 10 /* start every 10 seconds */, TimeUnit.SECONDS);
and when you need to stop the periodic task, just issue
periodicTask.cancel(true);
I am using the JSON parser to parse some pages but I would like to recall the parsing function every 30 seconds. How can i do that ?
One of the method to call a method every 30 seconds is by using postDelay of Handler see below code.
Handler handler;
handler=new Handler();
handler.removeCallbacks(run);
handler.post(run);
Runnable run=new Runnable()
{
public void run()
{
parsing();
handler.postDelayed(run,30000);
}
};
Another approach is by using "AlarmManager"
That is a weird need, only parsing when necessary would probably be a lot better.
Anyway, you should have a look at Timers and background services but be sure of what you are doing : if you create a background service that make a network call twice every minute, if that call is costly, you could cost a lot of data and/or battery to your users which is not a good idea.
You can do it using a timer.
Timer myTimer = new Timer();
After that you can call use the schedule method to call your json parser method.
myTimer.schedule(new TimerTask()
{
public void run() {
timerMethod();
}
}, 0, 1000);
private void timerMethod()
{
this.runOnUiThread(doSomething);
}
private Runnable doSomething = new Runnable() {
public void run() {
// Your code for doing something
}
Every 5 seconds, I want to call my webservice and get text (not images), then display it in my ImageAdapter. What would be the best way to accomplish this?
final Handler handler = new Handler();
final Runnable r = new Runnable()
{
public void run()
{
callWebservice();
}
};
handler.postDelayed(r, 5000);
It depends if you want to use a different thread or not. Do you want the user to be able to interact with the application on the UI Thread while the images are downloading? If so, then I would definitely use an AsyncTask with a small ProgressBar (style="#android:style/Widget.ProgressBar.Small")
If you don't care about threading then what #inazaruk said.
Edit: the truth is most modern apps that retrieve data from a web service will use an AsyncTask with a discreet little loader in the corner just to let the user know it's updating.
Edit 2: here's an example of using a TimerTask to run something every 5 seconds. The key is the runOnUiThread(). There may be better ways to tie all the elements together but this accurately portrays all the pieces.
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
CallWebService();
}
}, 0, 1000);
}
private void CallWebService()
{
this.runOnUiThread(fetchData);
}
private Runnable fetchData = new Runnable() {
public void run() {
asyncTask.execute();
}
};
You should call asynctask inside the application main thread. Asynctask can't be called in a background thread.