我正在后台线程中的活动中运行代码。为什么以下两个语句的行为不同?
A)
RunOnUiThread (() => Toast.MakeText(this, "A toast", ToastLength.Short).Show ());
b)中
RunOnUIThread (Toast.MakeText(this, "A toast", ToastLength.Short).Show);
(b)中的代码抛出以下异常:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
所以它看起来像(b)不在UI线程上运行,但为什么呢?
答案 0 :(得分:2)
让我们先看看第二个例子,因为它更简单。
所以我们有一个方法RunOnUIThread
,它接受一个委托作为它的参数。要运行这行代码,我们首先需要将第一个参数的表达式计算为值,因此我们执行Toast.MakeText(this, "A toast", ToastLength.Short).Show
。这会在当前线程(可能是非UI线程)中立即调用MakeText
方法 ,以便创建任何类型MakeText
返回的对象。然后,我们将表示对该创建对象的Show
方法的调用的委托传递给RunOnUIThread
,该方法接受该委托并在UI线程上运行它。
现在该流程实际上并未完成。正如您所看到的,MakeText
正在抛出异常,因为您在非UI线程中运行它,所以事情正在破坏。
第一段代码,当它去评估第一个参数的值时,不需要评估任何而不是说有一个方法(由lambda定义)执行运行时Toast.MakeText(this, "A toast", ToastLength.Short).Show()
。它不会评估任何代码以创建此委托;它是传递给ShowOnUiThread
的委托的正文的一部分。所以这一切都在UI线程中运行,并且工作正常。