【问题标题】:Kotlin using coroutines from worker thread to wait & get something from UI ThreadKotlin 使用来自工作线程的协程来等待并从 UI 线程获取一些东西
【发布时间】:2019-09-25 12:05:29
【问题描述】:

假设您在WorkerThread 中执行一项长时间运行的任务。但是,为了完成上述长时间运行的任务,您必须从UI Thread 获取一些东西

基本上,我需要访问 UI 线程,它将生成一个对象,该对象必须在 UI 线程上初始化,然后可以在任何线程中使用。

我想做的可能是使用协程/挂起函数,其中工作线程实际上等待 UI 线程上的操作完成。

我怎样才能做到这一点?谢谢!

以下是我打算实现的架构:

@WorkerThread
fun processTask() {
    // ... do some stuff to init work
    val something = getSomethingFromUiThread() // wait
    // ... resume & complete stuff with "something"
}

@MainThread
suspend fun getSomethingFromUiThread() {
    // ... create object on UI Thread
    // ... return initialized object to the worker thread
}

希望对你有帮助。

【问题讨论】:

    标签: android multithreading kotlin kotlin-coroutines


    【解决方案1】:

    你可以试试这样的:

    GlobalScope.launch(Dispatchers.Main) { //Your Main UI Thread
                  val myuithreadobject = myobject()
                   withContext(Dispatchers.IO) {
                   //this is out background thread
                            nodelist = ArrayList()
                           val info = myuithreadobject
    
                           printAllViews(info)
    
                        }
                  //after background thread is finished
            //do work on main thread
                }
    

    【讨论】:

    • 谢谢!差不多就是这样。我已经编辑了我的问题以添加模式。我的约束是我在一个工作线程上调用的方法中。不是相反。
    • 有了这个解决方案,我们如何在两个协程之间进行通信?我们如何在两个协程之间发送和接收消息。它只是在第一个协程中使用其他协程的上下文来执行该段代码
    • 实际上我认为@mr-patel 是对的,因为我设法用GlobalScope.async(...).wait() 创建了我的getSomethingFromUiThread,但调用此方法的方法也必须是可挂起的。但我不能这样做,我正在覆盖父类的方法。所以无论如何,我认为他的答案是正确的。一旦我得到它的工作,我会验证它。除非有办法拥有真正的阻塞方法?但是,它不再是关于协程......
    【解决方案2】:

    使用Dispatchers.MainDispatchers.IO 可能允许您使用不同的上下文,但我们需要了解启动一个新的协程并不等同于启动一个新线程。协程是轻量级线程。对于通信,您需要使用一些称为Channels 的概念。请参考此link

    类似地使用通道,您可以将线程中的协程链接到另一个线程中的协程

    【讨论】:

      【解决方案3】:

      只需在您的类中实现 CoroutineScope 并将您的类中的变量定义为

       private val job = Job()
       override val coroutineContext: CoroutineContext
       get() = job + Dispatchers.Main
      

      现在你可以像在课堂上那样做:-

      launch(Dispatchers.Main) {
          val data = async(Dispatchers.IO) {
              // do your work in background thread
          }.await()
          //And now data return on UI thread
      }
      

      示例:-

          Class MyClassFragment: Fragment(), CoroutineScope {
      private val job = Job()
      override val coroutineContext: CoroutineContext
          get() = job + Dispatchers.Main
      
      override fun onActivityCreated(savedInstanceState: Bundle?) {
          super.onActivityCreated(savedInstanceState)
      
          launch(Dispatchers.Main) {
              val data = async(Dispatchers.IO) {
                  // do your background operation
              }.await()
              //And now data return on UI thread
          }
      }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-16
        • 1970-01-01
        • 2021-10-28
        • 1970-01-01
        • 2019-06-19
        • 2018-10-01
        • 1970-01-01
        • 2020-12-13
        相关资源
        最近更新 更多