如何停止 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()
}
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()
}