IntentService中的强制停止循环功能

Force stop loop function in IntentService

我的意图服务中有一个功能类似于倒计时。它被称为counter

在 MainActivity 中执行某些操作后,应将什么添加到 IntentService 或直接添加到 counter 以停止此循环?

class IntentServiceExample : IntentService("Loop_test") {
    private val CHANNEL_ID = "ForegroundService Kotlin"

    companion object {
        val PARAM_OUT_MSG = "None"
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(CHANNEL_ID, "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT)
            val manager = getSystemService(NotificationManager::class.java)
            manager!!.createNotificationChannel(serviceChannel)
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        createNotificationChannel()

        val notificationIntent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this,
            0, notificationIntent, 0
        )
        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Foreground Service Kotlin Example")
            .setContentText("kylsha")
            .setSmallIcon(R.drawable.ic_notification)
            .setContentIntent(pendingIntent)
            .build()

        startForeground(1, notification)

        return super.onStartCommand(intent, flags, startId)
    }

    override fun onHandleIntent(p0: Intent?) {
        Toast.makeText(this,"Service started",Toast.LENGTH_LONG).show()

        val broadcastIntent = Intent()
        broadcastIntent.action = "com.example.intenttest.action.RESPONSE"
        broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
        sendBroadcast(broadcastIntent)
        counter(broadcastIntent)
    }

    fun counter(bc: Intent){
        for (i in 1..100){
            bc.putExtra(PARAM_OUT_MSG, i.toString())
            Thread.sleep(1000)
            d("number", i.toString())
            sendBroadcast(bc)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        stopSelf()

    }
}

在 class 中创建一个变量。 创建一个 setter 以将变量设置为 true。 在您的 rcounter 例程中,检查正在设置的变量。

private val cancelCounter = false
public fun setToCancel() {
    cancelCounter = true
}

/*Stuff*/

fun counter(bc: Intent){
    for (i in 1..100){
        if (cancelCounter) {
            cancelCounter = false
            break
        }
        bc.putExtra(PARAM_OUT_MSG, i.toString())
        Thread.sleep(1000)
        d("number", i.toString())
        sendBroadcast(bc)
    }
}

您可能无法从 main 直接访问该对象 - 如果不能,那么您应该使用单例模式创建此 class ;)

我在 kotlin 中编写的代码不够多,现在 "right way" 可以做到这一点,但一些链接指向正确的方法: https://blog.mindorks.com/how-to-create-a-singleton-class-in-kotlin https://medium.com/swlh/singleton-class-in-kotlin-c3398e7fd76b

这两个链接都提供了一些信息,说明它们为何在结构模式中做出决定,以及实现背后的代码如何工作;)

对于同样学习 Kotlin 的人,我也会 post 我的解决方案。看起来很简单,但是,可能会有更多的解决方案。

我创建了一个简单的 Kotlin 对象,例如:

object Trigger {
    var triggerStop = 0
    fun getTrigger(): Int{
        return triggerStop
    }
}

如您所见,变量 triggerStop 可以更改并使用函数 getTrigger()

调用

所以我将这个对象添加到 MainActivity 到按钮的 setOnClickListeners:

class MainActivity : AppCompatActivity() {
    lateinit var i:Intent
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        i = Intent(this, IntentServiceExample::class.java)

        buttonStart.setOnClickListener{
            Trigger.triggerStop = 0 // this variable will be checked in IntentService
            startService(i)
        }
        buttonEnd.setOnClickListener{
            Trigger.triggerStop = 1 // this variable will be checked in IntentService
            stopService(i)
        }
    }
}

然后我将这个对象放入我的 IntentService 中。在一个我想被用户交互停止的循环中,我像@Watachiaieto 的回答一样进行了检查。

fun counter(bc: Intent){
    for (i in 1..100){
        val stopIt = Trigger.getTrigger() // get trigger value
        if (stopIt == 1) {
            break
        }
        bc.putExtra(PARAM_OUT_MSG, i.toString())
        Thread.sleep(1000)
        sendBroadcast(bc)
    }
}