问题
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.
回答1:
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
回答2:
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);
回答3:
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
来源:https://stackoverflow.com/questions/33041573/android-create-a-background-thread-that-runs-periodically-and-does-ui-tasks