Service v/s AsyncTask

2019-05-08 16:23发布

问题:

I am confused with respect to design of my app. I need to continuously poll a server to get new data from it. I am confused whether Async Task running at fixed interval or Service running is background is better option. The thread will run only when the app is running

回答1:

You have already some answers to your question, but I think it worths a summary ...

What you need

When you want to run a peice of code that takes some time to complete you should always run it in a separate thread from the UI thread.

You can achieve that in 2 ways:

Using Thread:

This is the simplest one, if you don't need a lot of communication from the new thread to the UI thread. If you need the communication, you will probably have to use a Handler to do it.

Using AsyncTask:

Also runs in a separate thread and already implements some communications channels with the UI thread. So this one is preferable if you need this communication back to the UI.

What you don't need

Service

This serves mainly to keep some code running even after you exit the main application, and it will run in the UI thread unless you spawn a new thread using the options described above. You said that your thread are suposed to terminate when you exit application, so this is not what you need.

IntentService

This can be activated by an external event (i.e. BroadcastReceiver) that can start a piece of code defined by you, even if your application is not running. Once again, based on your requirements, this is not what you are looking for.

Regards.



回答2:

an Android Service is not in a background thread.

Therefore you should have a Service running that will start an ASyncTask each time you want to poll.

Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.



回答3:

Service should not be compared to AsyncTask. I guess you most likely meant IntentService here - and this is slightly different thing than Service, despite the common name.

As for periodical fetching, I'd stick with recurrent alarm (using AlarmManager) and (most likely) use IntentService to do the fetching.

Here you got with AsyncTask fundamentals and some tutorials And here you got with IntentService fundamentals and tutorials

Note, that IntentService jobs are queued by design, while AsyncTasks can run fully paralel. However be aware of regression related to AsyncTask handling in newer APIs. Not a big deal as workaround is just a few more code lines, however it's worth knowing that.

EDIT

There's misunderstanding floating among many concerning AsyncTask lifecycle being bond to Activity's life cycle. This is WRONG. AsyncTask is independent from an Activity. Finishing Activity does not do anything to any AsyncTasks, unless you are cleaning them up from onDestroy() by your code. Yet, if an activity's process is being killed while it is in the background, then AsyncTask will also be killed as well, as part of the entire process being killed



回答4:

If you want to "continuously poll", an asyncTask won't do. The task stops when your app gets stopped by Android. A Service by itself won't do either, as Blundell already pointed out. A Service runs in the main thread, and you don't want to do polling in the main thread. There's two ways of doing it: you create a Service that spawns its own thread to do the stuff you want it to do, or you let it schedule polls that are executed in an AsyncTask or in a separate thread. I try not to have polling in my app, but if you have to, creating a special thread in your service that does the polling seems best to me.

Depending on what your app does and what the polling is about, you can give the separate thread a lower priority, so it doesn't get in the way of other processing.



回答5:

The thread will run only when the app is running

Then AsyncTask will be the simplest solution. Send data periodically to app thread using publishProgress() from background thread. Set desired interval using Thread.sleep() in doInBackground(). Also, make sure you start a new task in onResume() method of Activity, and end this task in onPause() method of Activity.

Example:

public class MyActivity extends Activity {
    private AsyncTask<Void,String,Void> mAsyncTask;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mAsyncTask = new MyTask();
        mAsyncTask.execute();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if(mAsyncTask != null){
            mAsyncTask.cancel(true);
        }
    }

    private void onServerResponse(String response){
        Toast.makeText(this, "Got response !", Toast.LENGTH_SHORT).show();
    }

    private final class MyTask extends AsyncTask<Void,String,Void>{

        @Override
        protected Void doInBackground(Void... voids) {
            while (!isCancelled()){

                String response = "";

                //server query code here

                publishProgress(response);
                Log.i("TEST", "Response received");

                //sleep for 5 sec, exit if interrupted ,likely due to cancel(true) called
                try{
                    Thread.sleep(5000);
                }catch (InterruptedException e){
                    return null;
                }
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            if(values.length > 0){
                onServerResponse(values[0]);
            }
        }
    }
}