1. Service 是什么

Service 是 Android 中用于执行后台或前台任务的应用组件。它没有自己的 UI,可以在用户离开某个 Activity 后继续运行某些工作。

但是要注意:

Service 不是线程。
Service 默认运行在应用进程的主线程中。
Service 不会自动帮你创建子线程。

所以 Service 中不能直接执行耗时操作,否则可能导致 ANR。

正确理解:

Service = 组件生命周期与系统入口
Thread/Coroutine/Executor = 真正执行耗时任务的并发工具

2. Service 与 Thread 的区别

对比项

Service

Thread

本质

Android 应用组件

CPU 执行单元

是否有生命周期回调

有,如 onCreate()onStartCommand()onDestroy()

没有 Android 组件生命周期

是否默认在主线程

不是,取决于在哪里创建

是否能被系统组件启动

可以通过 Intent 启动或绑定

不可以

是否能直接更新 UI

在主线程中可以,但不建议承担 UI 职责

子线程不能直接更新 UI

典型用途

承载后台/前台任务、跨组件通信

执行耗时任务

示例:Service 内部开启协程处理任务:

class SyncService : Service() {
​
    private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
​
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        serviceScope.launch {
            try {
                syncData()
            } finally {
                stopSelf(startId)
            }
        }
        return START_NOT_STICKY
    }
​
    override fun onBind(intent: Intent?): IBinder? = null
​
    override fun onDestroy() {
        serviceScope.cancel()
        super.onDestroy()
    }
}

3. Service 的类型

现代 Android 中,可以从使用场景上分为:

类型

含义

典型场景

Started Service

通过 startService()startForegroundService() 启动

播放音乐、短期同步任务

Bound Service

通过 bindService() 绑定

Activity 与 Service 通信、进程内服务接口

Foreground Service

前台服务,必须显示通知

导航、运动记录、音频播放

Background Service

后台服务

Android 8.0 以后受到严格限制

4. 在 Manifest 中声明 Service

<service
    android:name=".SyncService"
    android:exported="false" />

如果是前台服务,还需要声明权限和类型,例如媒体播放:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
​
<application ...>
    <service
        android:name=".MusicService"
        android:exported="false"
        android:foregroundServiceType="mediaPlayback" />
</application>

5. startService 启动方式

启动:

val intent = Intent(this, SyncService::class.java)
startService(intent)

Service 中处理:

class SyncService : Service() {
    override fun onCreate() {
        super.onCreate()
        // 只在 Service 首次创建时调用一次
    }
​
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // 每次 startService 都会回调这里
        return START_NOT_STICKY
    }
​
    override fun onBind(intent: Intent?): IBinder? = null
​
    override fun onDestroy() {
        // 清理资源
        super.onDestroy()
    }
}

停止:

stopService(Intent(this, SyncService::class.java))

或者 Service 内部:

stopSelf()
stopSelf(startId)

6. bindService 启动方式

Bound Service 适合让 Activity 调用 Service 中的方法。

Service:

class PlayerService : Service() {

    inner class LocalBinder : Binder() {
        fun getService(): PlayerService = this@PlayerService
    }

    private val binder = LocalBinder()

    override fun onBind(intent: Intent): IBinder {
        return binder
    }

    fun play() {
        // 播放音乐
    }

    fun pause() {
        // 暂停音乐
    }
}

Activity:

class MainActivity : AppCompatActivity() {

    private var service: PlayerService? = null
    private var bound = false

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
            val localBinder = binder as PlayerService.LocalBinder
            service = localBinder.getService()
            bound = true
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            bound = false
            service = null
        }
    }

    override fun onStart() {
        super.onStart()
        bindService(
            Intent(this, PlayerService::class.java),
            connection,
            Context.BIND_AUTO_CREATE
        )
    }

    override fun onStop() {
        if (bound) {
            unbindService(connection)
            bound = false
        }
        super.onStop()
    }
}

7. onStartCommand 返回值

onStartCommand() 必须返回一个整型常量,告诉系统 Service 被杀后如何处理。

返回值

含义

适合场景

START_NOT_STICKY

被杀后不主动重建,除非还有待处理 Intent

普通一次性任务

START_STICKY

被杀后重建,但不一定重新传递旧 Intent

音乐播放等常驻任务

START_REDELIVER_INTENT

被杀后重建,并重新传递最后的 Intent

下载、上传等需要恢复的任务

8. 面试回答模板

问题:Service 和 Thread 有什么区别?

可以这样回答:

Service 是 Android 组件,用来承载后台或前台任务的生命周期和系统入口;Thread 是执行代码的线程。Service 默认运行在主线程,不会自动开子线程,所以耗时操作仍然要自己放到 Thread、线程池或协程中执行。Service 可以在 Activity 销毁后继续运行,但并不意味着它适合所有后台任务,Android 8.0 以后后台服务受到限制,很多延迟任务应该用 WorkManager。