1、一般主線程可以直接更新UI
創(chuàng)新互聯(lián)成立于2013年,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元鄢陵做網(wǎng)站,已為上家服務(wù),為鄢陵各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:13518219792
2、runOnUiThread
3、Task-onPostExecute
直接在UI線程中開(kāi)啟子線程來(lái)更新TextView顯示的內(nèi)容,運(yùn)行程序我們會(huì)發(fā)現(xiàn),如下錯(cuò)誤:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.翻譯過(guò)來(lái)就是:只有創(chuàng)建這個(gè)控件的線程才能去更新該控件的內(nèi)容。
所有的UI線程要去負(fù)責(zé)View的創(chuàng)建并且維護(hù)它,例如更新冒個(gè)TextView的顯示,都必須在主線程中去做,我們不能直接在UI線程中去創(chuàng)建子線程,要利用消息機(jī)制:handler,如下就是handler的簡(jiǎn)單工作原理圖:
既然android給我們提供了Handler機(jī)制來(lái)解決這樣的問(wèn)題,請(qǐng)看如下代碼:
public class HandlerTestActivity extends Activity { private TextView tv; private static final int UPDATE = 0; private Handler handler = new Handler() { @Overridepublic void handleMessage(Message msg) { // TODO 接收消息并且去更新UI線程上的控件內(nèi)容if (msg.what == UPDATE) { // Bundle b = msg.getData();// tv.setText(b.getString("num")); tv.setText(String.valueOf(msg.obj)); } super.handleMessage(msg); } }; /** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView) findViewById(R.id.tv); new Thread() { @Overridepublic void run() { // TODO 子線程中通過(guò)handler發(fā)送消息給handler接收,由handler去更新TextView的值try { for (int i = 0; i 100; i++) { Thread.sleep(500); Message msg = new Message(); msg.what = UPDATE; // Bundle b = new Bundle();// b.putString("num", "更新后的值:" + i);// msg.setData(b); msg.obj = "更新后的值:" + i; handler.sendMessage(msg); } } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); }}
我們就通過(guò)Handler機(jī)制來(lái)處理了子線程去更新UI線程控件問(wèn)題,Andrid開(kāi)發(fā)中要經(jīng)常用到這種機(jī)制。
android中有下列幾種異步更新ui的解決辦法:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
long) View.postDelayed(Runnable, long)
使用handler(線程間通訊)(推薦)
AsyncTask(
1、在主線程中啟動(dòng)一個(gè)子線程
首先,我們需要在主線程中啟動(dòng)一個(gè)子線程,這個(gè)比較簡(jiǎn)單,直接在MainActivity的onCreate()方法中調(diào)用如下方法即可:
new?Thread(mRunnable).start();
2、在子線程中發(fā)送Message給Handler
在創(chuàng)建子線程時(shí),我們使用了Runnable接口對(duì)象mRunnable。這里,只需要實(shí)現(xiàn)Runnable接口,并重寫(xiě)該接口的run()方法,在run()方法中實(shí)現(xiàn)每1秒發(fā)送一條Message給Handler即可。具體實(shí)現(xiàn)方法如下:
/*
*?Function???:???實(shí)現(xiàn)run()方法,每1秒發(fā)送一條Message給Handler
*/
private?Runnable?mRunnable?=?new?Runnable()?{
public?void?run()?{
while(true)?{
try?{
Thread.sleep(1000);
mHandler.sendMessage(mHandler.obtainMessage());
}?catch?(InterruptedException?e)?{
e.printStackTrace();
}
}
}
};
3、Handler接收Message通知
最后,我們創(chuàng)建一個(gè)Handler對(duì)象,用來(lái)接收Message通知。在收到Message通知后,完成刷新UI的操作即可。具體實(shí)現(xiàn)方法如下:
/*
*?Function???:???實(shí)現(xiàn)handleMessage()方法,用于接收Message,刷新UI
*/
private?Handler?mHandler?=?new?Handler()?{
public?void?handleMessage(Message?msg)?{
super.handleMessage(msg);
refreshUI();
}
};
4、刷新UI
由以上的代碼可以看出,刷新UI的操作,我們是放在refreshUI()方法中來(lái)完成的。refreshUI()方法的實(shí)現(xiàn)也很簡(jiǎn)單,調(diào)用HttpUtils工具類(lèi)中的getInputStream()方法,獲得圖1所示W(wǎng)eb工程的頁(yè)面內(nèi)容輸入流,再將該輸入流轉(zhuǎn)化為字符串,放入TextView控件中進(jìn)行顯示即可。具體實(shí)現(xiàn)方法如下:
/*
*?Function???:???刷新UI
*/
private?void?refreshUI()?{
try?{
InputStream?inputStream?=?HttpUtils.getInputStream();
String?resultData?=?HttpUtils.getResultData(inputStream);
mTextView.setText(resultData);
}?catch?(IOException?e)?{
e.printStackTrace();
}
}
Android屏幕的刷新包含3個(gè)步驟:CPU計(jì)算屏幕數(shù)據(jù)、GPU進(jìn)一步處理和緩存、最后屏幕(Display)再?gòu)木彺嬷邪延?jì)算的屏幕數(shù)據(jù)顯示出來(lái)
對(duì)于 Android 而言,第一個(gè)步驟: CPU 計(jì)算屏幕數(shù)據(jù) 指的也就是 View 樹(shù)的繪制過(guò)程,也就是 Activity 對(duì)應(yīng)的視圖樹(shù)從根布局 DecorView 開(kāi)始層層遍歷每個(gè) View,分別執(zhí)行測(cè)量、布局、繪制三個(gè)操作的過(guò)程。我們重點(diǎn)分析的也是這個(gè)步驟,關(guān)于后續(xù)的2個(gè)步驟我們可以理解為底層處理,沒(méi)必要過(guò)于深入。
我們知道Android每隔16.6ms會(huì)發(fā)送一次垂直同步VSync信息量,1S也就是60幀的畫(huà)面。下面這個(gè)圖藍(lán)色的是CPU計(jì)算屏幕數(shù)據(jù)時(shí)間戳,綠色的是GPU的處理,最后黃色的是屏幕。我們可以清楚的看到,每幀的畫(huà)面都會(huì)提前一幀去計(jì)算以及GPU處理。
如果我們保持頁(yè)面靜止,那么Android還是會(huì)16.6ms發(fā)送一次垂直同步信號(hào)量,App這個(gè)時(shí)候接受不到屏幕刷新的信號(hào)。所以也就不會(huì)讓 CPU 去計(jì)算下一幀畫(huà)面數(shù)據(jù),但是底層仍然會(huì)以固定的頻率來(lái)切換每一幀的畫(huà)面,只是它后面切換的每一幀畫(huà)面都一樣,所以給我們的感覺(jué)就是屏幕沒(méi)刷新
我們都知道Android的刷新離不開(kāi)ViewRootImpl,在上一篇文章 《Android中UI的繪制流程》 中,大致闡述了Android的UI刷新流程。這里我們進(jìn)一步深入的理解源碼,以及刷新UI的詳細(xì)流程。首先看圖:
當(dāng)前名稱(chēng):android的UI更新,安卓更新界面
轉(zhuǎn)載來(lái)源:http://aaarwkj.com/article42/dsiecec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、網(wǎng)站設(shè)計(jì)、虛擬主機(jī)、網(wǎng)站策劃、標(biāo)簽優(yōu)化、品牌網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容