Service详解

服务(Service)是Android中实现程序后台运行的解决方案,它的运行不依赖于任何用户界面,适合去执行那些不需要和用户交互且需要长期运行的任务。

注意

  • Service并不是运行在一个独立的进程中,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。
  • 服务并不会自动开启线程,所有的代码都默认运行在主线程中。所以,我们需要在服务内部手动创建子线程,并在这里执行具体的任务,避免出现主线程阻塞的情况。

生命周期
onCreate():服务第一次创建的时候调用的
onStartCommand():每次启动服务的时候都会调用
onBind():绑定服务的时候调用
onUnBind():解绑服务的时候调用
onDestory():销毁服务的时候调用

Service生命周期.png
Service生命周期测试Log结果.jpg

补充:

  • 每个服务都只会存在一个实例,不管调用了多少次startService or bindService方法,只需要调用一次stopService(或stopSelf)or unbindService方法,服务就会停止。
  • 一个服务只要被启动或被绑定之后,就会一直处于运行状态,必须让上述两种条件同时不满足,服务才能被销毁。

启动方式对比

启动方式 终止方式 特点
startService() 启动服务的控件调用stopService or 服务内部自己调用stopSelf or 依赖的进程销毁 不需要获取服务的数据,服务不随控件的销毁而终止
bindService() 绑定服务的控件调用unbindService or 绑定服务的控件销毁 or 依赖的进程销毁 需要获取服务的数据,服务随着控件的销毁而终止

注意:

  • 没有调用bindService直接调用unbindService会出现异常:
    java.lang.IllegalArgumentException: Service not registered;
    没有调用startService直接调用stopService则没事

服务的分类

Service分类.png

前台服务了解
前台服务会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏可以看到更加详细的信息,类似于通知的效果。使用前台服务,可以防止服务由于系统内存不足等原因被回收掉,而且可以满足一些特殊需求显示信息。

public class MyService extends Service {
   
    @Override
    public void onCreate() {
        super.onCreate();
        
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
        Notification notification = new NotificationCompat.Builder(this)
                .setContentTitle("this is title")
                .setContentText("I'm SO HAPPY")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.smile)
                .setContentIntent(pendingIntent)
                .build();
        startForeground((int) (Math.random() * 100), notification);
    }
}

IntentService了解
IntentService是一个用于处理异步请求的基类,客户端通过startService发送请求。该服务按需启动,用子线程依次处理每个Intent,并且当它执行完成时自动停止。内部实现机制为Handler。

/**
 * IntentService is a base class for {@link Service}s that handle asynchronous
 * requests (expressed as {@link Intent}s) on demand.  Clients send requests
 * through {@link android.content.Context#startService(Intent)} calls; the
 * service is started as needed, handles each Intent in turn using a worker
 * thread, and stops itself when it runs out of work.
 *
 * 

This "work queue processor" pattern is commonly used to offload tasks * from an application's main thread. The IntentService class exists to * simplify this pattern and take care of the mechanics. To use it, extend * IntentService and implement {@link #onHandleIntent(Intent)}. IntentService * will receive the Intents, launch a worker thread, and stop the service as * appropriate. * *

All requests are handled on a single worker thread -- they may take as * long as necessary (and will not block the application's main loop), but * only one request will be processed at a time. * * @see android.os.AsyncTask */ public abstract class IntentService extends Service { private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery; private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } } /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public IntentService(String name) { super(); mName = name; } /** * Sets intent redelivery preferences. Usually called from the constructor * with your preferred semantics. * *

If enabled is true, * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_REDELIVER_INTENT}, so if this process dies before * {@link #onHandleIntent(Intent)} returns, the process will be restarted * and the intent redelivered. If multiple Intents have been sent, only * the most recent one is guaranteed to be redelivered. * *

If enabled is false (the default), * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent * dies along with it. */ public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public void onCreate() { // TODO: It would be nice to have an option to hold a partial wakelock // during processing, and to have a static startService(Context, Intent) // method that would launch the service & hand off a wakelock. super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } /** * You should not override this method for your IntentService. Instead, * override {@link #onHandleIntent}, which the system calls when the IntentService * receives a start request. * @see android.app.Service#onStartCommand */ @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { mServiceLooper.quit(); } /** * Unless you provide binding for your service, you don't need to implement this * method, because the default implementation returns null. * @see android.app.Service#onBind */ @Override @Nullable public IBinder onBind(Intent intent) { return null; } /** * 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 {@link #stopSelf}. * * @param intent The value passed to {@link * android.content.Context#startService(Intent)}. * This may be null if the service is being restarted after * its process has gone away; see * {@link android.app.Service#onStartCommand} * for details. */ @WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent); }

你可能感兴趣的:(Service详解)