最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 中 Service 用法和最佳實踐

 更新時間:2026年04月27日 10:00:30   作者:學(xué)習(xí)使我健康  
本文介紹了Android中Service的使用場景、啟動方式、綁定方式、前臺服務(wù)等,并提供了常見的代碼示例和最佳實踐,幫助開發(fā)者正確使用Service組件,避免踩坑,感興趣的朋友跟隨小編一起看看吧

這篇就講一件事:Service 到底什么時候用,怎么用,怎么不踩坑。

你可以先把 Service 理解成:
“App 沒有頁面展示時,仍然需要在后臺繼續(xù)干活的一個組件”。
就像關(guān)注博主,下次容易找到一樣。
點點關(guān)注一下
常見場景:

  • 音樂后臺播放
  • 文件上傳下載
  • 定位持續(xù)上報
  • 藍牙設(shè)備連接與通信

1. 先記住這 3 句話

  1. Service 不是線程,它默認(rèn)也跑在主線程。
  2. 耗時任務(wù)不能直接寫在 Service 里,不然容易 ANR。
  3. 真正長期運行的后臺任務(wù),通常要做成前臺服務(wù)(帶通知)。

2. Service 有兩種常用玩法

簡單說:

  • 啟動式:我讓你去干活,你自己干完自己停。
  • 綁定式:我需要一直和你通信,比如“播放/暫停/下一首”。

2.1 啟動式 Service(Started Service)

啟動方式:

  • startService(intent)(老方式)
  • Android 8+ 更常見 startForegroundService(intent)(配合前臺服務(wù))

適合場景:

  • 同步數(shù)據(jù)
  • 上傳日志
  • 一次性后臺處理

核心回調(diào):

  • onCreate():第一次創(chuàng)建時調(diào)用一次
  • onStartCommand():每次啟動都會進來
  • onDestroy():銷毀時調(diào)用

停止方式:

  • 在服務(wù)里 stopSelf()
  • 外部 stopService(intent)

2.2 綁定式 Service(Bound Service)

綁定方式:bindService(intent, conn, flags)

適合場景:

  • 音樂播放器控制
  • 下載進度回調(diào)
  • 頁面和服務(wù)需要頻繁交互

核心回調(diào):

  • onCreate()
  • onBind()(返回 IBinder
  • onUnbind() / onRebind()
  • onDestroy()

一句話理解:
頁面拿到 IBinder 后,就能像調(diào)用普通對象一樣調(diào)用服務(wù)方法。

3. 生命周期怎么理解更簡單

啟動式

onCreate() -> onStartCommand()(可能多次)-> onDestroy()

onStartCommand() 返回值怎么選:

  • START_NOT_STICKY:被系統(tǒng)殺了就算了,不自動重建(一次性任務(wù)常用)
  • START_STICKY:系統(tǒng)盡量拉起來,但 Intent 可能沒了
  • START_REDELIVER_INTENT:系統(tǒng)重建時,把上次 Intent 再給你一次

綁定式

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

4. 什么是前臺服務(wù)(Foreground Service)

你可以把前臺服務(wù)理解成:
“系統(tǒng)允許你長時間后臺運行,但你必須給用戶一個持續(xù)通知,告訴用戶你在做什么。”

從 Android 8 開始,后臺限制變嚴(yán)格,很多長期任務(wù)都要走前臺服務(wù)。

基本要求:

  1. startForegroundService(intent) 啟動
  2. 很快調(diào)用 startForeground(notificationId, notification)
  3. 通知必須可見(不能偷偷跑)

Android 14+ 額外注意:

  • Manifest 里寫 foregroundServiceType
  • 類型要和實際任務(wù)對應(yīng)(如 mediaPlayback、location、dataSync
  • 相關(guān)權(quán)限要補齊(通知、定位等)

5. 代碼示例(可直接參考)

5.1 啟動式 Service(Kotlin)

class SyncService : Service() {
    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
    override fun onCreate() {
        super.onCreate()
        // 初始化資源
    }
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        scope.launch {
            try {
                // 執(zhí)行耗時任務(wù)
                doSync()
            } finally {
                // 任務(wù)結(jié)束后停止服務(wù)
                stopSelf(startId)
            }
        }
        return START_NOT_STICKY
    }
    override fun onBind(intent: Intent?): IBinder? = null
    override fun onDestroy() {
        super.onDestroy()
        scope.cancel()
    }
    private suspend fun doSync() {
        // TODO: 執(zhí)行同步邏輯
    }
}

啟動和停止:

ContextCompat.startForegroundService(context, Intent(context, SyncService::class.java))
// 或 context.startService(intent)(低版本或非前臺需求)
context.stopService(Intent(context, SyncService::class.java))

5.2 綁定式 Service(Kotlin)

class MusicService : Service() {
    private val binder = LocalBinder()
    inner class LocalBinder : Binder() {
        fun getService(): MusicService = this@MusicService
    }
    override fun onBind(intent: Intent): IBinder = binder
    fun play() {
        // 播放邏輯
    }
    fun pause() {
        // 暫停邏輯
    }
}

Activity 綁定:

class MainActivity : AppCompatActivity() {
    private var musicService: MusicService? = null
    private var bound = false
    private val conn = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder = service as MusicService.LocalBinder
            musicService = binder.getService()
            bound = true
        }
        override fun onServiceDisconnected(name: ComponentName?) {
            bound = false
            musicService = null
        }
    }
    override fun onStart() {
        super.onStart()
        bindService(
            Intent(this, MusicService::class.java),
            conn,
            Context.BIND_AUTO_CREATE
        )
    }
    override fun onStop() {
        super.onStop()
        if (bound) {
            unbindService(conn)
            bound = false
        }
    }
}

6. Manifest 配置

<service
    android:name=".service.MusicService"
    android:exported="false"
    android:foregroundServiceType="mediaPlayback" />

說明:

  • android:exported="false":只給自己 App 用,默認(rèn)更安全
  • 只有真的要給其他 App 調(diào)用,才考慮 exported="true",并加權(quán)限保護

7. 到底該不該用 Service

這些情況適合用 Service

  • 用戶能感知到、而且要持續(xù)運行的任務(wù)(音樂、導(dǎo)航、運動)
  • App 切后臺后,任務(wù)還要繼續(xù)

這些情況不建議直接用 Service

  • 一次性、可延遲、要求“最終一定執(zhí)行”的任務(wù) -> 優(yōu)先 WorkManager
  • 頁面內(nèi)短耗時任務(wù) -> 協(xié)程 + 生命周期組件就夠了

8. 常見問題與最佳實踐

  • 別在主線程做重活
    • Service 默認(rèn)是主線程,耗時操作請放協(xié)程/線程池。
  • 干完就停
    • 任務(wù)完成后及時 stopSelf(),別讓服務(wù)白跑。
  • 前臺服務(wù)別濫用
    • 有持續(xù)通知會打擾用戶,必須有明確業(yè)務(wù)價值。
  • 注意系統(tǒng)版本差異
    • Android 8+ 后臺限制、Android 13+ 通知權(quán)限、Android 14+ 前臺服務(wù)類型都要適配。
  • 考慮被系統(tǒng)殺進程
    • 按業(yè)務(wù)選好 onStartCommand() 返回值,并做好狀態(tài)恢復(fù)。
  • 跨進程通信是進階題
    • 真要給其他 App 調(diào)用,通常走 AIDL + 權(quán)限控制。

9. 一句話總結(jié)

Service 適合“沒頁面但要持續(xù)干活”的任務(wù):
只管執(zhí)行用啟動式,需要交互控制用綁定式,長期后臺任務(wù)優(yōu)先做前臺服務(wù)并按系統(tǒng)版本補齊權(quán)限和類型聲明。

到此這篇關(guān)于Android 中 Service 用法的文章就介紹到這了,更多相關(guān)Android Service 用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

泰兴市| 固安县| 建水县| 海盐县| 商南县| 富平县| 临泽县| 绥德县| 普安县| 高安市| 黄骅市| 中江县| 青浦区| 彝良县| 安阳市| 西贡区| 昌黎县| 达州市| 根河市| 噶尔县| 古田县| 洛南县| 农安县| 安化县| 贵阳市| 鄂托克旗| 防城港市| 历史| 铅山县| 景泰县| 曲阳县| 新建县| 潮安县| 阿拉善右旗| 西乌珠穆沁旗| 南投县| 兴和县| 林西县| 怀宁县| 许昌县| 苍南县|