問題:如何實現每隔5s鍾更新一下標題。
學過Java多線程的同學,肯定會想,這還不簡單!於是乎有了以下的代碼:
public class MainActivity extends Activity {
private int count = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new TitleThread()).start();
}
class TitleThread implements Runnable {
@Override
public void run() {
while (true) {
setTitle("Welcome to my blog" + count++);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
趕緊興致勃勃的運行,可是運行時會報錯:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
這個錯誤究竟是什麼東東?
翻譯過來的意思是:只有原始創建這個視圖層次(view hierachy)的線程才能修改它的視圖(view)。也就是說必須在一般必須在程序的主線程(也就是ui)線程中進行更新界面顯示的工作。
http://jackxlee.blog.51cto.com/2493058/686161 這篇文章有詳細的說明
總結一下:試圖在自定義的線程中更新視圖(如本例我們是不斷的刷新標題)是無法做到的,Android引入了Handler這個特殊類,它架起了Runnable和Activity之間的橋樑。
Handler
在線程的run方法裏發送Message,而在Handler裏,根據不同的Message執行不同的任務。
public class MainActivity extends Activity {
private int count = 1;
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
updateTitle();
break;
default:
break;
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new TitleThread()).start();
}
protected void updateTitle() {
setTitle("Welcome to my blog" + count++);
}
class TitleThread implements Runnable {
@Override
public void run() {
while (true) {
Message message=new Message();//創建一條消息
message.what=1;//編碼指定
handler.sendMessage(message);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
對於線程的創建也可以採用Timer這個類結合TimerTask來實現
public class TimerActivity extends Activity {
private int count = 1;
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
updateTitle();
break;
default:
break;
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Timer timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Message message=new Message();
message.what=1;
handler.sendMessage(message);
}
}, 1000,5000);
}
protected void updateTitle() {
setTitle("Welcome to my blog" + count++);
}
}