首先,android的UI刷新是在主線程(UI線程)中完成的。四大組件中,activity和service運行在主線程中。現(xiàn)在總結自己在項目中常用到的UI刷新方式。

網站建設公司,為您提供網站建設,網站制作,網頁設計及定制網站建設服務,專注于成都定制網站,高端網頁制作,對人造霧等多個行業(yè)擁有豐富的網站建設經驗的網站建設公司。專業(yè)網站設計,網站優(yōu)化推廣哪家好,專業(yè)營銷推廣優(yōu)化,H5建站,響應式網站。
第一,利用子線程發(fā)消息刷新UI。
子線程負責處理UI需要的數據,然后發(fā)消息到主線程來刷新UI。代碼結構如下:
new Thread(new Runnable() {
@Override
public void run() {
Person person=new Person();
person.setName(mName.getText().toString().trim());
person.setPhone(mPhone.getText().toString().trim());
Log.i("person",person.toString());
DatabaseInfoFactory.getPersonDao(mContext).addPerson(person);
Looper.prepare();
Message msg=Message.obtain();
msg.what=0x123456;
handler.sendMessage(msg);
Looper.loop();
}
}).start();
主線程中:
private Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
if(msg.what==0x123456||msg.what==0x123){
fillData();
setListener();
}
}
};
第二,利用異步任務更新UI。代碼結構如下:
new AsyncTaskvoid,void,void() {
@Override
protected void onPostExecute(Void result) {
if(mAdapter==null){
mAdapter=new LeaveInfoAdapter();
//設置數據適配器
mLVleaveInfos.setAdapter(mAdapter);
Log.i("測試", "異步任務顯示后臺獲得數據庫數據");
}
else {
mAdapter.notifyDataSetChanged();
}
super.onPostExecute(result);
}
@Override
protected Void doInBackground(Void... params) {
//獲得要顯示的數據
mleaveInfos=mLeaveInfosDao.findAll();
if (mleaveInfos==null) {
Toast.makeText(HomeActivity.this,"請假數據不存在或是已經清除!", 500).show();
}
Log.i("測試", "異步任務后臺獲得數據庫數據"+mleaveInfos.size());
return null;
}
}.execute();/void,void,void
第三,利用配置文件+activity的生命周期方法刷新UI。
利用Looper更新UI界面
2.AsyncTask利用線程任務異步更新UI界面
3.利用Runnable更新UI界面
1、在主線程中啟動一個子線程
首先,我們需要在主線程中啟動一個子線程,這個比較簡單,直接在MainActivity的onCreate()方法中調用如下方法即可:
new?Thread(mRunnable).start();
2、在子線程中發(fā)送Message給Handler
在創(chuàng)建子線程時,我們使用了Runnable接口對象mRunnable。這里,只需要實現(xiàn)Runnable接口,并重寫該接口的run()方法,在run()方法中實現(xiàn)每1秒發(fā)送一條Message給Handler即可。具體實現(xiàn)方法如下:
/*
*?Function???:???實現(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)建一個Handler對象,用來接收Message通知。在收到Message通知后,完成刷新UI的操作即可。具體實現(xiàn)方法如下:
/*
*?Function???:???實現(xiàn)handleMessage()方法,用于接收Message,刷新UI
*/
private?Handler?mHandler?=?new?Handler()?{
public?void?handleMessage(Message?msg)?{
super.handleMessage(msg);
refreshUI();
}
};
4、刷新UI
由以上的代碼可以看出,刷新UI的操作,我們是放在refreshUI()方法中來完成的。refreshUI()方法的實現(xiàn)也很簡單,調用HttpUtils工具類中的getInputStream()方法,獲得圖1所示Web工程的頁面內容輸入流,再將該輸入流轉化為字符串,放入TextView控件中進行顯示即可。具體實現(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();
}
}
思考:
先必須了解下面2個問題
1.顧名思義 UI線程 就是刷新UI 所在線程
2.UI是單線程刷新
1.對Activity 來說 UI線程就是其主線程
2.對View來說 UI線程就是創(chuàng)建ViewRootImpl所在的線程
可以通過 WindowManager 內部會創(chuàng)建ViewRootImpl對象
好了,進入主題。我們來慢慢揭開面紗。
我們可以分別從幾個方面切入
我們可能都有使用過 runOnUiThread 現(xiàn)在來看看的源碼實現(xiàn)。
可以從上面的源碼 看到
不是UI線程 就用Handler切到Handler所在的線程中,如果是UI線程直接就調用run方法。
Activity的創(chuàng)建:
1.Activity創(chuàng)建:mInstrumentation.newActivity
2.創(chuàng)建Context :ContextImpl appContextcreateBaseContextForActivity(r)
我們經常用這個方法干的事情就是,要么在onCreate中獲取View寬高的值。要么就是在子線程中做一些耗時操作 ,然后post切到對應View所在的線程 來繪制UI操作。那么這個對應的線程就是UI線程了。
那么這個UI線程就一定是主線程嗎?
接來繼續(xù)來看。它的源碼View:post
mAttachInfo 在dispatchAttachedToWindow 中被賦值 ,也就是在ViewRootImpl創(chuàng)建的時候,所以是創(chuàng)建ViewRootImpl所在的線程。
attachInfo 上面時候為null 呢?在ViewRootImpl 還沒來得及創(chuàng)建的時候,ViewRootImpl 創(chuàng)建是在 “onResume" 之后。所以在 Activity 的 onCreate 去View.post 那么AttachInfo 是為null 。
當 AttachInfo == null 那么會調用 getRunQueue().post(action) 。
最終這個Runnable 被 緩存到 HandlerActionQueue 中。
直到ViewRootImpl 的 performTraversals 中 調用dispatchAttachedToWindow(mAttachInfo, 0);, 那么才會去處理 RunQueue() 中的Runnable。
來張圖 便于理解這個流程
我們有時候去子線程操作UI的時候(如:requestLayout),會很經常見到下面的 報錯日志:
Only the original thread that created a view hierarchy can touch its views
為什么會報這個錯誤呢?
翻譯一下:只有創(chuàng)建視圖層次結構的原始線程才能接觸到它的視圖。
也就是操作UI的線程要和ViewRootImpl創(chuàng)建的線程是同一個線程才行,并不是只有主線程才能更新UI啊。
ViewRootImpl創(chuàng)建的線程?那么 ViewRootImpl 在哪里被創(chuàng)建的呢?
從上圖可以看到ViewRootImpl創(chuàng)建最開始是從 ActivityThread 的HandleResumeActivity中開始 一直 ViewRootImpl 創(chuàng)建,也就是說ViewRootImpl 對應的UI線程和 ActivityThread 在同一個線程 也就是主線程。
好了 通過上面的講解,上面的問題相信你可以自己回答啦~
標題名稱:android更新ui,android更新版本下載
瀏覽路徑:http://chinadenli.net/article37/dsgjhsj.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供外貿網站建設、關鍵詞優(yōu)化、面包屑導航、網站制作、網站內鏈、品牌網站制作
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)