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。