Создайте сервис, который работает, когда активность открыта - PullRequest
0 голосов
/ 05 февраля 2020

Я хочу создать Службу, которая выполняет сетевую операцию, но я хочу, чтобы она работала, пока активность открыта. Поэтому я хочу связать это в жизненном цикле деятельности. Если пользователь переходит к другому виду деятельности и обратно, я хочу, чтобы он перезапустился. Если экран гаснет и пользователь снова открывает его, я хочу, чтобы он запустился снова, если невозможно сохранить его

class PushService: Service() {

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

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // ToDo Create the request that i want
    }
}

Так что мне нужно запускать и останавливать службу в onResume и onStop в Activity?

 override fun onResume() {
        super.onResume()

        Intent(this, PushService::class.java).also { intent ->
            startService(intent)
        }
    }

    override fun onStop() {
        super.onStop()

        stopService(Intent(this, PushService::class.java))
    }

Я не уверен, как это сделать. Кто-нибудь знает правильный путь?

Может быть, было бы неплохо просто создать процесс, который я хочу, внутри ViewModel вместо запуска службы для него?

1 Ответ

1 голос
/ 05 февраля 2020

Вы в основном делаете это правильно, за исключением того, что вы должны либо использовать onResume / onPause, либо onStart / onStop, не смешивая две пары. onStart и onStop вызываются только тогда, когда ваша деятельность полностью выходит из поля зрения. Таким образом, в вашем примере, если перед вами появилось диалоговое окно из другого приложения, onStop не будет вызвано, но onResume будет вызвано, поэтому ваша уже запущенная служба получит несколько вызовов onStartCommand.

Однако весь смысл Сервисов - запускать операции, которые продолжаются, когда ваше приложение не видно. Если вы этого не делаете, было бы проще написать свой собственный класс (возможно, который реализует LifecycleObserver или заимствует lifecycleScope из Activity) для обработки фоновой работы. Тогда вам не придется иметь дело с регистрацией в манифесте и обработкой намерений.

Пример LifecycleObserver:

// lifecycle is a property of AppCompatActivity. You can instantiate this class
// from your activity.onCreate()
class MyNeworkTaskManager(lifecycle: Lifecycle): LifecycleObserver, CoroutineScope by lifecycle.coroutineScope {

    init {
        lifecycle.addObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    private fun onResume() {
        startMyRequest()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    private fun onPause() {
        pauseOrCancelMyRequest()
    }

    // Alternatively, if you want to expose suspend functions so your activity can request 
    // and respond to data in a coroutine without callbacks:
    suspend fun getMyData(args: String): MyData {
        val results = someNetworkRequestSuspendFunction(args)
        return MyData(results)
    }

    // Or if you want to use coroutines for your network request, but still want
    // your activity to use callbacks so it doesn't have to use coroutines to call
    // these functions:
    fun getMyDataAsync(args: String, callback: (MyData) -> Unit) = launch {
        val results = someNetworkRequestSuspendFunction(args)
        callback(MyData(results))
    }

}

Я сам не очень много работаю с сетями. Но какую бы библиотеку вы не использовали, вы обычно можете конвертировать обратные вызовы в сопрограммы, используя suspendCancellableCoroutine. Для этого есть учебники.

...