我是安卓新手。我了解到不允許在后臺執行緒中訪問 UI 組件,但是我遇到的情況讓我感到困惑。我做了以下。
(1) 我使用“Empty Activity”模板創建了一個帶有包名com.example.myapplication和最低 SDK 版本 29 的新 Android Studio 專案。
(2) 我更改了activity_main.xml,添加了一個按鈕和一個 TextView,其中android:layout_widthTextView 的設定為wrap_content。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:id="@ id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="@ id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>

(3)我改MainActivity.kt了,給按鈕加了一個點擊監聽,啟動一個執行緒,改變執行緒中TextView的文本。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView = findViewById<TextView>(R.id.textView)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
thread {
textView.text = "Accessing textView from ${Thread.currentThread().name}"
}
}
}
}
(4) 我在 API 31 模擬器中啟動了應用程式,然后單擊了按鈕。該應用程式因以下錯誤而崩潰:
2022-03-29 23:48:42.364 24327-24360/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.myapplication, PID: 24327
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
這是預期的行為。但是當我將android:layout_widthTextView 的屬性更改為match_parent(或固定寬度,如100dp),重新構建并啟動應用程式,然后再次單擊按鈕時,TextView 的文本已成功更改。執行緒名稱表明我肯定是從后臺執行緒訪問 TextView。

為什么會這樣?為什么一個TextView的layout_width屬性可以決定從后臺執行緒訪問UI組件是否成功?
uj5u.com熱心網友回復:
您絕對可以從后臺執行緒訪問 UI 執行緒。
您應該注意,如果將 TextView 設定為 ,則保存 TextView 的ViewGroup( LinearLayout) 負責它的寬度和高度match_parent。
這意味著TextView在運行時對寬度或高度的每個動態更改都必須在 UI 執行緒上運行,而不是從后臺執行緒運行。這就解釋了這個例外
2022-03-29 23:48:42.364 24327-24360/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.myapplication, PID: 24327
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
上述例外中的基調是:
只有創建視圖層次結構的原始執行緒才能接觸其視圖
由于創建ViewGroup( LinearLayout) 的是 UI 執行緒,因此僅允許 UI 執行緒在ViewGroup其子視圖上運行布局更改。
android:layout_width現在,當您給出有限值時,例外被解決的原因100dp是因為有限值意味著 UI 執行緒(創建 )不會有任何動態布局更改ViewGroup需要擔心。
您將在運行時進行的唯一更改是顯示的值,這不會TextView更改其布局結構(因為您android:layout_width已將100dpandroid:layout_heightwrap_content
您唯一應該擔心的android:layout_height是當您在另一個不是 UI 執行緒的執行緒中TextView動態更改字體大小或高度時。
現在在另一個執行緒中訪問 UI 執行緒。做這個:
button.setOnClickListener {
thread {
runOnUiThread {
textView.text = "Accessing textView from ${Thread.currentThread().name}"
}
}
}
上面的代碼片段從后臺執行緒訪問 UI 執行緒。
我希望這有幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/452677.html
上一篇:一次停止多個執行緒
