java ui线程_UI线程异常处理方法
UI線程是非線程安全的,所以,不能在工作線程中操作UI元素。
兩個(gè)原則
Do not block the UI thread (不要阻塞UI線程)
Do not access the Android UI toolkit from outside the UI thread (不要在工作線程中操作UI元素)
在工作線程更新UI方法
Activity.runOnUiThread(Runnable)
Handler
sendMessage(Message)
post(Runnable)
AsyncTask
execute()
doInBackground()
onPostExecute()
例子程序
HandlerActivity01
在工作線程中進(jìn)行UI操作。
HandlerActivity02
Handler的兩個(gè)重要方法:sendMessage和post。
HandlerActivity03
官方推薦最佳方法。
HandlerActivity01主要代碼:
Java代碼
btnEnd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run()
{
//在新建的線程(工作線程)中改變Button的文字
btnEnd.setText("Text Changed in Sub Thread");
}
}).start();
}
});
這是一種錯(cuò)誤的做法,運(yùn)行程序,會(huì)報(bào)錯(cuò)誤:
Java代碼
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
HandlerActivity02主要代碼:
Java代碼
public class HandlerActivity02 extends Activity
{
private int title = 0;
Button btnStart,btnEnd;
private Handler mHandler = new Handler()
{
public void handleMessage(Message msg)
{
//更新UI
switch (msg.what)
{
case 1:
updateTitle();
break;
}
};
};
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnStart = (Button)findViewById(R.id.start);
btnEnd = (Button)findViewById(R.id.end);
//新啟動(dòng)一個(gè)線程,進(jìn)行耗時(shí)操作
Timer timer = new Timer();
//每六秒執(zhí)行一次MyTask的run方法
timer.scheduleAtFixedRate(new MyTask(this), 1, 6000);
}
private class MyTask extends TimerTask
{
private Activity context;
MyTask(Activity context)
{
this.context = context;
}
@Override
public void run()
{
//耗時(shí)操作略....
//更新UI方法 1
Message message = new Message();
message.what = 1;
mHandler.sendMessage(message);
//更新UI方法 2
mHandler.post(updateThread);
//更新UI方法 3
context.runOnUiThread(updateThread);
}
}
public void updateTitle()
{
setTitle("Welcome to Mr Wei‘s blog " + title);
title++;
}
Runnable updateThread = new Runnable()
{
@Override
public void run()
{
//更新UI
btnStart.setText(String.valueOf(title));
btnEnd.setText(String.valueOf(title));
}
};
}
這里有個(gè)容易出錯(cuò)的地方,在更新UI方法2和3中,我們傳入的參數(shù)是一個(gè)Runnable對(duì)象,一般認(rèn)為這就會(huì)啟動(dòng)一個(gè)新的線程,而且常有人在這個(gè)Runnable對(duì)象的run方法中進(jìn)行耗時(shí)操作。看過(guò)這塊的源碼就會(huì)知道,其實(shí),android只是調(diào)用了這個(gè)Runnable對(duì)象的run方法而已,并沒(méi)有啟動(dòng)新的線程,而且我們不應(yīng)該在run方法中進(jìn)行耗時(shí)操作,因?yàn)檫@個(gè)run方法最終是在UI線程里面執(zhí)行的。也就是說(shuō),run方法里面只應(yīng)該放更新UI的代碼,handleMessage方法也一樣。
如果你要看這部分源代碼的話,相信這個(gè)圖對(duì)你會(huì)有幫助:
HandlerActivity03主要代碼:
Java代碼
public class HandlerActivity03 extends Activity
{
Button btnStart;
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnStart = (Button)findViewById(R.id.start);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//開(kāi)始執(zhí)行AsyncTask,并傳入某些數(shù)據(jù)
new LongTimeTask().execute("New Text");
}
});
}
private class LongTimeTask extends AsyncTask
{
@Override
protected String doInBackground(String... params)
{
try
{
//線程睡眠5秒,模擬耗時(shí)操作,這里面的內(nèi)容Android系統(tǒng)會(huì)自動(dòng)為你啟動(dòng)一個(gè)新的線程執(zhí)行
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return params[0];
}
@Override
protected void onPostExecute(String result)
{
//更新UI的操作,這里面的內(nèi)容是在UI線程里面執(zhí)行的
btnStart.setText(result);
}
}
}
這個(gè)方法確實(shí)挺好,因?yàn)樗鼮槟惴庋b了許多操作,你只需要記住在doInBackground方法中寫(xiě)耗時(shí)操作的代碼,在onPostExecute方法中寫(xiě)更新UI的方法就行了
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的java ui线程_UI线程异常处理方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于多层html标签嵌套引起CSS冲突问
- 下一篇: MySQL查询对NULL的处理