Android开发中,正确认识和使用Service

2,811 阅读3分钟

我正在参加「掘金·启航计划」

前言

Service(服务)是 Android 四大组件之一,主要作用是执行后台操作,Android中 Activity 提供了 UI 界面可与用户交互,而 Service 则没有 UI 界面,所有操作都是在后台完成。

Service 与 Activity 一样也可由其它应用程序启动,即使用户切换到其它应用,Service 仍可保持在后台运行。

一个组件可以与 Service 进行绑定(bind)来与 Service 进行交互,亦可以进行进程间通信(IPC)。 平常开发中使用 Service 进行网络请求、播放音乐、文件 I/O 等操作。

Service的使用

创建Service

自定义一个类继承 Service 并实现对应方法来创建Service

public class TestService extends Service {

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

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    return super.onStartCommand(intent, flags, startId);
  }

  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public boolean onUnbind(Intent intent) {
    return super.onUnbind(intent);
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
  }
}

注意:所有自定义的 Service 都需要在 Manifest 里进行声明

<manifest ... >
  ...
  <application ... >
    <service android:name="xxx.TestService" />
    ...
  </application>
</manifest>

在 <service> 标签里将 android:exported 属性设置为 false 可防止其他程序来启动自己App的 Service。

启动Service

通常情况下有两种方式来启动 Service,调用startService() 和 bindService()

  • startService 方式启动
Intent intent = new Intent(context, TestService.class);
// 开启服务
startService(intent);
// 停止服务
stopService(intent); 

其他组件通过调用 startService() 启动 Service 后,Service 可在后台无限期运行,即使启动 Service 的组件被销毁也不受影响。 一般情况下 startService() 是执行单一操作,不会将执行结果返回给调用者。例如,可能是下载文件或者上传文件,操作完成后会自动停止。

这种方式允许多个组件同时对同一 Service 进行 startService() 操作,但只要有其中有一个组件调用了 stopSelf() 或 stopService(), 该 Service 就会被销毁。

  • bindService() 方式启动
Intent intent = new Intent(this, TestService.class);
ServiceConnection connection = new ServiceConnection() {
  @Override
  public void onServiceConnected(ComponentName name, 
                                 IBinder service) {
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
  }
};
// 绑定服务
bindService(intent, connection, Context.BIND_AUTO_CREATE);
// 解绑服务
unbindService(aidlConnection);

组件通过调用 bindService() 启动 Service ,Service 就处于绑定状态。提供 client - service 的接口,可让调用者与 Service 进行发送请求和返回结果的操作,还可以进行进程间的通信(IPC)。

一个组件对该 Service 进行绑定,那该 Service 就不会销毁。若多个组件同时对一个 Service 进行绑定,只有全部绑定的该 Service 的组件都解绑后,Service 才会销毁。

注意使用 startService() 启动 Service 后,也是可以进行绑定的。

虽然 Service 是在后台运行,但其实还是在主线程中进行所有的操作。Service 启动时除非单独进行了定义,否则没有单独开启线程或者进程都运行在主线程中。

任何能阻塞主线程的操作(如:播放音乐或者网络请求),应该在 Service 中单独开启新线程来进行操作,否则很容易出现 ANR。

重写几个重要方法

onCreate()

第一次启动 Service 时会调用此方法,用于初始化。若 Service 已启动,该方法不会再被调用。

onStartCommand()

一个组件通过调用 startService() 来启动 Service 时,会调用该方法。执行该方法后,Service 会启动并在后台无限期执行。

实现该方法,在 Service 执行完后,需要调用 stopSelf() 或 stopService() 来结束Service。

onBind()

某个组件通过调用 bindService() 绑定的方式来启动 Service 时,会调用该方法。实现此函数时,要返回一个 IBinder 的继承类,来与 Service 进行通信。

这个是默认必须要重写的,若不想通过绑定的方式来启动 Service,可以直接返回 null

onDestroy()

Service 被销毁时,会回调该方法。若有用到 thread、listeners、receivers 等,应该将这些对象的回收清理写在该方法内。

Service生命周期

Service 同样有生命周期回调方法

01.png

startService 方式的方法回调

onCreate() -> onStartCommand() -> onDestroy()

bindService 方式的方法回调

onCreate() -> onBind() -> onUnbind() -> onDestroy()