简体   繁体   中英

Android Kotlin by Delegates.observable from background Thread into ViewModel

Premises: I have already read and tried all the solutions proposed in the other posts where other users had had the same exception

I have a thread that I start inside my app's onCreate

open class App : Application() {

   override fun onCreate() {

      Thread {
           ...
             }.start()
   }
}

at some point, always inside the thread, I have a class that wants to implement an observable variable using the 'by Delegates.observable'

class MyService{

    var myVariable: String by Delegates.observable("default value") { _, oldValue, newValue ->
        onVariableChanged?.invoke(oldValue, newValue)
    }
    var onVariableChanged: ((String, String) -> Unit)? = null

    fun doSomething(){

     myVariable = "result"

     // ----      I also tried the 2 solutions commented below  ----
//
//            val handler = Handler(getMainLooper())
//            handler.post {myVariable = "result"}

//            GlobalScope.launch {
//                withContext(Dispatchers.Main){
//                   myVariable = "result"
//                }
//            }


    }

}

Now I need that in the ViewModel I could be able to observe the variable that should update within the thread

class MyViewModel(application: Application) : AndroidViewModel(application) {

//     ---- I also tried with couroutines  --------
  //    private val viewModelJob = SupervisorJob()
//    private val viewModelScope = CoroutineScope(viewModelJob + Dispatchers.Main)  

 init {

//        viewModelScope.launch {
//            onVariableThreadChanged()
//        }

        onVariableThreadChanged()
      }

   private fun onVariableThreadChanged(){
           myServiceInstance.onVariableChanged = {oldValue , newValue ->
              .....
           }
   }

}

In reading the log file I see that in the method of the thread where I try to assign the value

myVariable = "result"

of the variable 'by Delegates.observable' gives me an exception

"Only the original thread that created a view hierarchy can touch its views."

I solved by putting the delegate inside the couroutineScope (Dispatchers.Main).launch {...} and moving the viewModel code inside the activity into the runOnUiThread {..} method

into MyService

  CoroutineScope(Dispatchers.Main).launch {
                            myVariable = "result"
                        }

into MyActivity

  runOnUiThread(
            myServiceInstance.onVariableChanged = {oldValue , newValue  ->
              .....
             }
         )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM