如何停止 Android 服务中的线程

How to stop thread inside Android service

java.lang.InterruptedException 错误被抛出 onDestroy 因为 Runnable 中的 Thread.sleep。我认为 Runnable 创建了一个新线程并允许休眠?

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var startBtn: Button
    lateinit var stopBtn: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        startBtn = findViewById(R.id.startButton)
        stopBtn = findViewById(R.id.stopButton)
        startBtn.setOnClickListener { startService() }
        stopBtn.setOnClickListener { stopService() }
    }

    private fun startService() {
        val serviceIntent = Intent(this, ForegroundService::class.java)
        ContextCompat.startForegroundService(this, serviceIntent)
    }

    private fun stopService() {
        val serviceIntent = Intent(this, ForegroundService::class.java)
        stopService(serviceIntent)
    }
}
ForegroundService.kt

class ForegroundService : Service() {
    private lateinit var thread: Thread

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel("channel_service", "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT)

            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)

            val notification: Notification = Notification.Builder(this, "channel_service")
                    .setContentTitle("Title")
                    .setContentText("Text")
                    .setSmallIcon(R.drawable.ic_launcher_foreground)
                    .build()

            startForeground(1, notification)

            runnable = TestRunnable()
            thread = Thread(runnable)
            thread.start()
        }

        return START_NOT_STICKY
    }

    override fun onDestroy() {
        if(thread.isAlive) {
            thread.interrupt()
        }
        super.onDestroy()
    }

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

    class TestRunnable : Runnable {
        override fun run() {
            for(i in 1..15) {
                Log.d("Debug", "startThread " + i)
                Thread.sleep(1000) //exception through here onDestroy
            }
        }
    }
}

添加线程=null;在 Thread(runnable).interrupt() 之后。这应该工作。如果您希望它在用户停止 activity 时被杀死,您应该尝试重写 onStop 而不是 onDestroy()。

希望对您有所帮助!快乐编码:)

使用thread.interrupt()中断线程。在 Thread.sleep(1000) 周围添加 try-catch 调用:

class TestRunnable : Runnable {
    override fun run() {
        var isInterrupted = false
        for(i in 1..15) {
            Log.d("Debug", "startThread " + i)
            try {
                Thread.sleep(1000)
            } catch (e: InterruptedException) {
                isInterrupted = true
            }
            if (isInterrupted) break
        }
    }
}

您还可以使用一些 AtomicBoolean 变量来打破 Runnable 实现中的循环:

class TestRunnable : Runnable {
    private val isStopped = AtomicBoolean(false)

    fun stop() {
        isStopped.set(true)
    }
     
    override fun run() {
        for(i in 1..15) {
            if (isStopped.get()) break
            // ...
        }
    }
}

override fun onDestroy() {
    if(thread.isAlive) {
        runnable.stop()
        thread.interrupt()
    }
    super.onDestroy()
}