Android UI操作并不是線程安全的并且這些操作必須在UI線程中執(zhí)行。Android利用Handler來實(shí)現(xiàn)UI線程的更新的。
Handler是Android中的消息發(fā)送器,其在哪個(gè)Activity中創(chuàng)建就屬于且緊緊屬于該Activity。還可以說其在哪個(gè)線程中new的,就是那個(gè)線程的Handler。
Handler的定義: 主要接受子線程發(fā)送的數(shù)據(jù), 并用此數(shù)據(jù)配合主線程更新UI.?
解釋: 當(dāng)應(yīng)用程序啟動(dòng)時(shí),Android首先會(huì)開啟一個(gè)主線程 (也就是UI線程) , 主線程為管理界面中的UI控件,進(jìn)行事件分發(fā), 比如說, 你要是點(diǎn)擊一個(gè) Button ,Android會(huì)分發(fā)事件到Button上,來響應(yīng)你的操作。 ?如果此時(shí)需要一個(gè)耗時(shí)的操作,例如: 聯(lián)網(wǎng)讀取數(shù)據(jù),或者讀取本地較大的一個(gè)文件的時(shí)候,你不能把這些操作放在主線程中,,如果你放在主線程中的話,界面會(huì)出現(xiàn)假死現(xiàn)象,如果5秒鐘還沒有完成 的話,會(huì)收到Android系統(tǒng)的一個(gè)錯(cuò)誤提示 "強(qiáng)制關(guān)閉".這個(gè)時(shí)候我們需要把這些耗時(shí)的操作,放在一個(gè)子線程中,因?yàn)樽泳€程涉及到UI更新,Android主線程是線程不安全的,也就是說,更新 UI只能在主線程中更新,子線程中操作是危險(xiǎn)的. 這個(gè)時(shí)候,Handler就出現(xiàn)了.來解決這個(gè)復(fù)雜的問題,由于Handler運(yùn)行在主線程中(UI線程中), ?它與子線程可以通過Message對(duì)象來傳遞數(shù)據(jù), 這個(gè)時(shí)候,Handler就承擔(dān)著接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對(duì)象,(里面包含數(shù)據(jù)),把這些消息放 入主線程隊(duì)列中,配合主線程進(jìn)行更新UI。
Handler一些特點(diǎn)?
handler可以分發(fā)Message對(duì)象和Runnable對(duì)象到主線程中, 每個(gè)Handler實(shí)例,都會(huì)綁定到創(chuàng)建他的線程中(一般是位于主線程),?
它有兩個(gè)作用:
(1)安排消息或Runnable 在某個(gè)主線程中某個(gè)地方執(zhí)行
(2)安排一個(gè)動(dòng)作在不同的線程中執(zhí)行?
Handler中分發(fā)消息的一些方法?
post(Runnable)?
postAtTime(Runnable,long)?
postDelayed(Runnable long)?
sendEmptyMessage(int)?
sendMessage(Message)?
sendMessageAtTime(Message,long)?
sendMessageDelayed(Message,long)?
以上post類方法允許你排列一個(gè)Runnable對(duì)象到主線程隊(duì)列中,?
sendMessage類方法, 允許你安排一個(gè)帶數(shù)據(jù)的Message對(duì)象到隊(duì)列中,等待更新.
?
補(bǔ)充別人總結(jié)的:------------------->
1、向哪個(gè)Handler 發(fā)送消息,就必須在哪個(gè)handler 里面接收;
2、直接使用JAVA 的 Thread 是無法更新Android UI的,因?yàn)锳ndroid View 在設(shè)計(jì)的時(shí)線程是不完全的,不過Android 提供了幾種供開發(fā)者在線程中更新UI的方法,如下:
runOnUiThread( Runnable )
post( Runnable )
postDelayed( Runnable, long )
3、直接使用hanlder.post 等方法是在當(dāng)前主線程里面做操作,而不是另外新建線程,建議使用Thread 線程直接新建另外一個(gè)線程或者使用HandlerThread類也可以。( 這句話的意思是ui線程是主線程,把一些耗時(shí)的操作放入其他線程做,主線程僅僅更新視圖)
4、記住消息隊(duì)列的先進(jìn)先出原則。?
?
需要注意的:
一. Handler與Thread的區(qū)別。
Handler與調(diào)用者處于同一線程,如果Handler里面 做耗時(shí)的動(dòng)作,調(diào)用者線程會(huì)阻塞。Android UI操作不是線程安全的,并且這些操作必須在UI線程中執(zhí)行。Android提供了幾種基本的可以在其他線程中處理UI操作的方案,包括Activity 的runOnUiThread(Runnable),View的post以及1.5版本的工具類AsyncTask等方案都采用了 Handler,Handler的post對(duì)線程的處理也不是真正start一個(gè)新的線程,而是直接調(diào)用了線程的run方法,這正是google煞費(fèi)苦心 搞一套Handler的用意。
?
二. Handler對(duì)于Message的處理不是并發(fā)的。
一個(gè)Looper 只有處理完一條Message才會(huì)讀取下一條,所以消息的處理是阻塞形式的。但是如果用不同的Looper則能達(dá)到并發(fā)的目的。Service 中,onStart的執(zhí)行也是阻塞的。如果一個(gè)startService在onStart執(zhí)行完成之前,再次條用startService也會(huì)阻塞。如果 希望能盡快的執(zhí)行onStart則可以在onStart中使用handler,因?yàn)镸essage的send是非阻塞的。如果要是不同消息的處理也是并發(fā) 的,則可以用不同的Looper實(shí)例化Handler。
?
三.?資源回收
向Handler對(duì)象發(fā)送類似new Message ()形式的空Message可以達(dá)到清空Message的目的,這種做法與getLooper().quit()的做法是一樣的。如果利用的資源較多,應(yīng)及時(shí)清理。
--------------------->
?
Handler的post(Runnable r)和postDelayed(Runnable r, long l);
Java代碼? public?class?SimpleHandlerTest?extends?Activity?{??????private?static?final?String?TAG?=?"SimpleHandlerTest";??????private?MyView?myView;??????private?Handler?mHandler;????????@Override??????protected?void?onCreate(Bundle?savedInstanceState)?{??????????super.onCreate(savedInstanceState);??????????requestWindowFeature(Window.FEATURE_NO_TITLE);????????????myView?=?new?MyView(this);??????????mHandler?=?new?Handler()?{??????????????@Override??????????????public?void?handleMessage(Message?msg)?{??????????????????super.handleMessage(msg);??????????????????switch?(msg.what)?{??????????????????case?1:??????????????????????myView.invalidate();??????????????????????break;??????????????????}??????????????}??????????};??????????????????????mHandler.post(update);??????????????????????setContentView(myView);??????}????????private?Runnable?update?=?new?Runnable()?{??????????@Override??????????public?void?run()?{??????????????myView.update();??????????????mHandler.postDelayed(update,?10);??????????}??????};????????class?MyView?extends?View?{??????????private?float?x?=?0f;????????????public?MyView(Context?context)?{??????????????super(context);??????????}????????????public?void?update()?{??????????????postInvalidate();??????????}????????????@Override??????????protected?void?onDraw(Canvas?canvas)?{??????????????super.onDraw(canvas);??????????????x++;??????????????Paint?paint?=?new?Paint();??????????????paint.setAntiAlias(true);??????????????paint.setColor(Color.RED);??????????????canvas.drawRect(x,?40,?x?+?40,?80,?paint);??????????????canvas.drawCircle(x,?40,?40,?paint);??????????}??????}????????@Override??????public?boolean?onCreateOptionsMenu(Menu?menu)?{??????????menu.add(1,?1,?1,?"下個(gè)頁面");??????????return?super.onCreateOptionsMenu(menu);??????}????????@Override??????public?boolean?onMenuItemSelected(int?featureId,?MenuItem?item)?{??????????if?(item.getItemId()?==?1)?{??????????????startActivity(new?Intent(this,?Update.class));??????????}??????????return?super.onMenuItemSelected(featureId,?item);??????}??}?? ?
Java代碼 public?class?Update?extends?Activity?{??????public?ProgressDialog?pBar;??????private?Handler?handler?=?new?Handler();????????@Override??????protected?void?onCreate(Bundle?savedInstanceState)?{??????????super.onCreate(savedInstanceState);??????????setContentView(R.layout.smt);??????????Dialog?dialog?=?new?AlertDialog.Builder(Update.this).setTitle("系統(tǒng)更新")??????????????????.setMessage("發(fā)現(xiàn)新版本,請(qǐng)更新!")??????????????????.setPositiveButton("確定",??????????????????????????new?DialogInterface.OnClickListener()?{??????????????????????????????@Override??????????????????????????????public?void?onClick(DialogInterface?dialog,??????????????????????????????????????int?which)?{??????????????????????????????????pBar?=?new?ProgressDialog(Update.this);??????????????????????????????????pBar.setTitle("正在下載");??????????????????????????????????pBar.setMessage("請(qǐng)稍候...");??????????????????????????????????pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);??????????????????????????????????downFile("http://localhost:8080/examples/images/Blockx_3D.apk");??????????????????????????????}??????????????????????????}).setNegativeButton("取消",??????????????????????????new?DialogInterface.OnClickListener()?{??????????????????????????????public?void?onClick(DialogInterface?dialog,??????????????????????????????????????int?whichButton)?{????????????????????????????????????????????????????????????????}??????????????????????????}).create();??????????dialog.show();??????}????????void?downFile(final?String?url)?{??????????pBar.show();??????????new?Thread()?{??????????????public?void?run()?{??????????????????HttpClient?client?=?new?DefaultHttpClient();????????????????????????????????????HttpGet?get?=?new?HttpGet(url);??????????????????HttpResponse?response;??????????????????try?{??????????????????????response?=?client.execute(get);??????????????????????HttpEntity?entity?=?response.getEntity();??????????????????????long?length?=?entity.getContentLength();??????????????????????InputStream?is?=?entity.getContent();??????????????????????FileOutputStream?fileOutputStream?=?null;??????????????????????if?(is?!=?null)?{??????????????????????????File?file?=?new?File(Environment??????????????????????????????????.getExternalStorageDirectory(),?"Blockx_3D.apk");??????????????????????????fileOutputStream?=?new?FileOutputStream(file);????????????????????????????byte[]?buf?=?new?byte[1024];??????????????????????????int?ch?=?-1;??????????????????????????int?count?=?0;??????????????????????????while?((ch?=?is.read(buf))?!=?-1)?{??????????????????????????????fileOutputStream.write(buf,?0,?ch);??????????????????????????????count?+=?ch;??????????????????????????????if?(length?>?0)?{??????????????????????????????}??????????????????????????}??????????????????????}??????????????????????fileOutputStream.flush();??????????????????????if?(fileOutputStream?!=?null)?{??????????????????????????fileOutputStream.close();??????????????????????}??????????????????????down();??????????????????}?catch?(ClientProtocolException?e)?{??????????????????????e.printStackTrace();??????????????????}?catch?(IOException?e)?{??????????????????????e.printStackTrace();??????????????????}??????????????}??????????}.start();??????}????????void?down()?{??????????handler.post(new?Runnable()?{??????????????public?void?run()?{??????????????????pBar.cancel();??????????????????update();??????????????}??????????});??????}????????void?update()?{??????????Intent?intent?=?new?Intent(Intent.ACTION_VIEW);??????????intent.setDataAndType(Uri.fromFile(new?File("/sdcard/Blockx_3D.apk")),??????????????????"application/vnd.android.package-archive");??????????startActivity(intent);??????}??}?
轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/3544135.html
總結(jié)
以上是生活随笔為你收集整理的Android中的Handler的具体用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。