Android 更新UI的兩個方法
在Android的開發過程中,常常需要適時的更新UI。Androd中的UI是在主線程中更新的。如果在主線程之外的線程中直接更新,就會出現報錯並拋出異常:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
只有原始創建這個視圖層次(view hierachy)的線程才能修改它的視圖(view)
那麼Android中該如何更新UI呢?
<1>. 利用Activity.runOnUiThread(Runnable)把更新UI的代碼寫在Runnable中
操作機制:如果當前線程是UI線程,那麼該行動立即執行;如果不是,操作發布到事件隊列的UI線程。
RunOnUiThreadDemo
布局文件:activity_mai.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello_world"
/>
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="點擊更新界面"
/>
<TextView
android:id="@+id/input_str"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
Java文件:MainActivity.java
package com.zsl.runonuithreaddemo;
import android.os.Bundle;
import android.app.Activity;
import android.text.Editable;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView viewText = (TextView)findViewById(R.id.input_str);
Button btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
char[] str = "Android is intresting...".toCharArray();
viewText.setText(str, 0, str.length);
}
});
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
運行結果:
<2>. 在Activity.onCreate(Bundle savedInstanceState)中創建一個Handler類的實例,利用Handler的回調實現。
具體參見:Android Handler消息傳遞機制 http://www.linuxidc.com/Linux/2013-07/87154.htm
事實上,我從這裡的一篇英文文章中了解到,Android的handler中也是通過runOnUiThread實現的。
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11