无法从协程 withContext(Dispatchers.Main.imidiate){} 更新 class 变量的值

Unable to update value of class variable from coroutine withContext(Dispatchers.Main.imidiate){}

我正在开发一个简单的程序,其中启动绑定服务并在服务内启动协程以每秒生成随机数,当单击获取数字按钮时,数字显示在文本视图中。这里的问题是我无法更新随机数(每次打印默认值)这是我的代码

主要Activity

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import androidx.appcompat.app.AppCompatActivity
import com.example.androidservice.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var serviceIntent: Intent
    private lateinit var binding: ActivityMainBinding
    private lateinit var mService: MyService
    private var serviceConnected = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        serviceIntent = Intent(this, MyService::class.java)

        binding.startService.setOnClickListener {
            if (!serviceConnected) {
                startService(serviceIntent)
                bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)
            }
        }

        binding.stopService.setOnClickListener {
            if (serviceConnected) {
                unbindService(connection); stopService(serviceIntent)
            }
        }

        binding.stopRandom.setOnClickListener { if (serviceConnected) mService.stopCount() }

        binding.getNumber.setOnClickListener {
            if (serviceConnected) binding.displayNumber.text = mService.getNumber()
        }


    }


    private  val connection: ServiceConnection=object :ServiceConnection{

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder=service as MyService.MyBinding
            mService=binder.getService()
            serviceConnected=true

        }

        override fun onServiceDisconnected(name: ComponentName?) {
            serviceConnected=false
        }

    }

}

服务class

import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.util.Log
import kotlinx.coroutines.*

class MyService: Service() {

    private  var binder= MyBinding() as IBinder
    private lateinit var job:Job
    private var random1 =9

    class MyBinding: Binder() {
        fun getService():MyService{ return MyService() }
    }
    override fun onBind(intent: Intent?): IBinder {
          return binder
    }

    override fun onDestroy() {
        super.onDestroy()

        Log.i("Stop Self invoked","stopSelf()")
    }


    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.i("In service thread id= ",Thread.currentThread().name)

    job= CoroutineScope(Dispatchers.IO).launch {
            while (true) {
                val random = (1..100).random()
                Log.i("Random number is = ", random.toString())
             //   setValueToMainThread(random)
                withContext(Dispatchers.Main.immediate){                   // here is the problem code
                  this@MyService.random1=random
                }
                delay(1000)
            }
        }

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


    fun stopCount(){ job.cancel()}
    fun getNumber():String {
      return  random1.toString()
    }

}

主要Activity XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/display_number"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Number"
        android:textSize="32sp"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.109" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/start_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Service"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.448" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/stop_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop Service"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.485"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.543" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/stop_random"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop Random"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.509"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.36" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/get_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="get number"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.657" />

</androidx.constraintlayout.widget.ConstraintLayout>

在调试时我发现 random1 的值正在改变,但是当从 onClick 调用 getNumber() 时,MyService class 的实例不一样。我不知道是什么问题。我创建了一个静态变量来保存 MyService 的实例,然后在协程中调用它。但是有没有其他方法可以更新 random1?

的值

您启动的服务实例和您用来取号的服务实例不同,因为

fun getService():MyService{ return MyService() }

getService() 将 return 每次您调用 MyService class 的新实例。

将您的 MyBinding class 更改为方法中的内部 class 和 return MyService 实例。

inner class MyBinding: Binder() {
    fun getService():MyService{ return this@MyService }
}