Android Service详解

本文详细解析了Android Service的启动方式、方法与常量、生命周期,包括Context.startService()、Context.bindService()及两者结合的使用场景,对比了不同启动方式下Service的生命周期差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

各位肯定知道 Service 作为 Android 的四大组件之一是非常重要的。不过说实话,我实际开发项目中服务用的并不多,(可能和需求有关吧)但是笔试的时候,几乎是必出的题目了,所以我们今天就来仔细的回顾一下 Service 。

1. 什么是服务?

Service 是表示应用程序需求的应用程序组件,在不与用户交互的情况下执行长时间运行的操作,或者给其他应用程序提供使用的功能。Service 是和应用程序在同一个进程中运行的,Service 并不是一个线程,所以它并不是用来处理耗时操作的。

2. 启动服务的方式有几种?(启动服务需要在 AndroidManifest.xml 文件配置)

  • Context.startService()
  • Context.bindService()
  • 先 Context.startService() 在 Context.bindService()

3. Service 的方法和常量有哪些?

ReturnMethode
final Application

getApplication()

返回拥有此服务的Application。

adstract IBinder

onBind(Intent intent)

将通信通道返回给服务。

void

onConfigurationChanged(Configuration newConfig)

当组件运行时,设备配置发生变化时由系统调用。

void

onCreate()

首次创建服务时由系统调用。

void

onDestroy()

由系统调用以通知服务它已不再使用且正在被删除。

void

onLowMemory()

当整个系统内存不足时调用此方法,并且主动运行的进程应调整其内存使用量。

void

onRebind()

当新客户端连接到服务时调用,在此之前,它已经被通知所有客户端在其onUnbind(Intent)中断开连接。

void

onStart(Intent intent,int startId)

此方法在API级别5中已弃用。请实现onStartCommand(Intent,int,int)。

int

onStartCommand(Intent intent,int flags,int startId)

每次客户端通过调用Context.startService(Intent)显式启动服务时,由系统调用,提供它提供的参数和表示启动请求的唯一整数标记。

void

onTaskRemoved(Intent rootIntent)

如果服务当前正在运行,且用户删除了来自服务应用程序的任务,则调用此函数。

void

onTrimMemory(int level)

当操作系统确定是进程从进程中删除不需要的内存的好时机时调用。

boolean

onUnbind(Intent intent)

当所有客户端与服务发布的特定接口断开连接时调用。

final void

startForeground(int flags)

将此服务从前台状态删除,允许在需要更多内存时终止该服务。

final void

startForeground(boolean removeNotification)

同 startForeground(int flags)

final void

startForeground(int id,Notification notification)

如果您的服务已启动(通过Context.startService(Intent)运行),则还要使此服务在前台运行,从而提供在此状态下向用户显示的持续通知。

final void

stopSelf()

停止服务,如果服务之前已经启动。

final void

stopSelf(int startId)

不再返回结果的旧版本的stopSelfResult(int)。

final boolean

stopSelfResult(int startId)

如果最近一次启动的是startId,则停止服务。

Constants
int

START_CONTINUATION_MASK

onStartCommand返回的位(Intent, int, int)描述了如果服务被终止,如何继续服务。

int

START_FLAG_REDELIVERY

如果Intent是先前传递的intent的重新传递,则此标志在onStartCommand(Intent,int,int)中设置,因为该服务先前已返回START_REDELIVER_INTENT但在为该Intent调用stopSelf(int)之前已被杀死。

int

START_FLAG_RETRY

如果意图是重试,则在onStartCommand(Intent, int, int)中设置此标志,因为初始尝试从未到达或从onStartCommand(Intent, int, int)返回。

int

START_NOT_STICKY

从onStartCommand(Intent,int,int)返回的常量:如果此服务的进程在启动时被终止(从onStartCommand(Intent,int,int)返回后),并且没有新的启动意图要传递给它,那么 将服务从启动状态中取出,并且在将来显式调用Context.startService(Intent)之前不要重新创建。

int

START_REDELIVER_INTENT

从onStartCommand(Intent,int,int)返回的常量:如果此服务的进程在启动时被终止(从onStartCommand(Intent,int,int)返回后),则它将被安排重新启动并且最后一次传递的Intent 通过onStartCommand(Intent,int,int)再次传递给它。

int

START_STICKY

从onStartCommand(Intent,int,int)返回的常量:如果此服务的进程在启动时被终止(从onStartCommand(Intent,int,int)返回后),则将其保留在启动状态但不保留此状态 交付 intent。

int

START_STICKY_COMPATIBILITY

从onStartCommand(Intent,int,int)返回的常量:START_STICKY的兼容版本,不保证在被杀死后再次调用onStartCommand(Intent,int,int)。

int

STOP_FOREGROUND_DETACH

stopForeground(int)的标志:如果设置,则先前提供给startForeground(int,Notification)的通知将与服务分离。

int

STOP_FOREGROUND_REMOVE

stopForeground(int)的标志:如果设置,将删除先前提供给startForeground(int,Notification)的通知。

4. 服务的生命周期

(1)Context.startService() 的生命周期。(和开启者的生命周期无关,如果不显示的停止 Service,Service 会一直运行。)

首次启动 Service 会先调用 onCreate() ,然后调用 onStartCommand(),至此 Service 任务就启动了。我们再次启动相同 Service,你会发现只调用了 onStartCommand(),也就是说 onCreate() 只会被调用一次,onStartCommand()会调用多次。当我们停止 Service 会调用 onDestroy(),至此 Service 就停止了。生命周期结束!

  • 测试代码:
public class MyService extends Service {

    public static final String TAG = "My_Service";

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

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "MyService --> onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "MyService --> onStartCommand");
        return START_STICKY;
    }

    
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "MyService --> onDestroy");
    }
}
 Intent intent = new Intent(ServiceActivity.this, MyService.class);
 startService(intent);
stopService(intent);
  • 第一次启动 Service 
 D/My_Service: MyService --> onCreate
 D/My_Service: MyService --> onStartCommand
  • 再次启动相同 Service
 D/My_Service: MyService --> onStartCommand
  • 当我们停止服务 Service
 D/My_Service: MyService --> onDestroy

 

(2)Context.bindService() 的生命周期。(和开启者的生命周期绑定,随着开启者的销毁而销毁)

首次启动 Service 会调用 onCreate() ,同样的也是只会调用一次。随后会调用 onBind() 。销毁 Service 会调用先调用onUnbind(),随后会调用 onDestroy()。至此生命周期结束!

  • 测试代码
public class MyService extends Service {

    public static final String TAG = "My_Service";

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG,"MyService --> onBind");
        return new MyBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG,"MyService --> onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "MyService --> onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "MyService --> onStartCommand");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "MyService --> onDestroy");
    }

    public class MyBinder extends Binder implements IPersonalInif{

        @Override
        public String getName() {
            return "Test Name";
        }
    }

    public interface IPersonalInif {
        String getName();
    }
}
public class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mInfoService = (MyService.IPersonalInif) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

        @Override
        public void onBindingDied(ComponentName name) {

        }
}
Intent intent = new Intent(ServiceActivity.this, MyService.class);
mMyServiceConnection = new MyServiceConnection();
bindService(intent, mMyServiceConnection, Service.BIND_AUTO_CREATE);
Log.d(TAG,"IPersonalInif --> name --> " + mInfoService.getName());
unbindService(mMyServiceConnection);
  • 第一次启动 Service
 D/My_Service: MyService --> onCreate
 D/My_Service: MyService --> onBind
  • 再次启动相同服务 Service

logcat 没有任何输出,也就是再次启动没有任何回调!

  • 我们尝试获取 Service 传递的值
 D/Service_Activity: IPersonalInif --> name --> Test Name
  • 解除 Service 的绑定
 D/My_Service: MyService --> onUnbind
 D/My_Service: MyService --> onDestroy

 

(3)先 Context.startService() 在 Context.bindService() 的生命周期。(这种方式的代码就不贴了,说说场景,和流程吧)

如果 Service 由某个客户端通过 Context.startService() 启动,接下来由其他客户端通过 Context.bindService() 绑定到该 Service,然后在调用 unbindService() 解除该 Service,然后在通过 Context.bindService() 绑定到该 Service,那么生命周期的步骤如下:

onCreate() --> onStartCommand --> onBind() --> onUnbind() --> onRebind()

注意:前提是 onUnbind() 返回 true,读到这里可能会有点疑惑,那就是我明明调用了 unbindService() 方法,系统为什么不调用 Service 的 onDestroy() 呢?这是因为 Service 是我们先 Context.startService() 启动的,所以系统只会调用 onUnbind(),不会调用 onDestroy()。(我们使用 Context.bindService() 绑定一个已经启动的 Service ,系统只是会将 Service 内部的 IBinder 对象传递给 Activity,并不会将 Service 的生命周期和 Activity 的生命周期绑定,所以我们即使调用 unbindService(),也是不会销毁 Service的)

 

至此,Service 的使用以及生命周期已经讲解完了,希望对你有帮助!

欢迎加入Q群一起探讨Android问题。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值