【问题标题】:Proper way to update UI from a class in Kotlin从 Kotlin 中的类更新 UI 的正确方法
【发布时间】:2018-09-19 11:36:00
【问题描述】:

我是 Android 开发的新手,我想知道从另一个类更新 UI 的最佳做法是什么。

示例:当我进入一个活动时,我启动了一个函数myClass.PerformCalculation(),这需要一些时间,当计算结束时,我想用计算结果更新 UI。 这会产生以下错误:

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

我正在考虑在活动中使用广播接收器并在myClass.PerformCalculation() 的末尾执行SendBroadcast,这是一个好习惯吗?

【问题讨论】:

  • 您应该将计算结果返回给活动并更新活动中的UI。不要使用广播
  • 感谢您的反馈。根据文档 ASyncTask 似乎是在我的情况下使用的正确方法。

标签: android kotlin


【解决方案1】:

这里是AsyncTask 的文档。

它将帮助您执行一些后台任务,并在完成后将结果发布到主 UI。

来自文档:

AsyncTask 允许正确且轻松地使用 UI 线程。这节课 允许您执行后台操作并在 无需操作线程和/或处理程序的 UI 线程。

代码示例:来自Stack Answer

inner class someTask() : AsyncTask<Void, Void, String>() {
    override fun doInBackground(vararg params: Void?): String? {
        // ...
    }

    override fun onPreExecute() {
        super.onPreExecute()
        // ...
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)
        // UPDATE UI HERE
    }
}

【讨论】:

    【解决方案2】:

    使用RxJava

    object MyClass {
        fun performCalculation(): Single<Int> {
            return Single.fromCallable {
                //perform calculation
                1
            }
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
        }
    }
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            MyClass.performCalculation().subscribe { result ->
                //update ui
            }
        }
    }
    

    使用Coroutines

    object MyClass {
        fun performCalculation(): Deferred<Int> {
            return async(CommonPool) {
                //your calculation
                1
            }
        }
    }
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            launch(UI) {
                val result = MyClass.performCalculation().await()
                //update ui
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-11-01
      • 1970-01-01
      • 2018-11-18
      • 1970-01-01
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多