-
截獲Handler要接收的消息
查看全部 -
Handler 作用:1 更新UI, 2發送消息,處理消息
查看全部 -
---轉: handler總結:<br> 1.不能直接在非UI線程直接更新UI(大多數時候)。<br> 2.每次創建Handler時需要給它綁定一個looper,如果是主線程不給定具體的looper則會綁定默認的looper。<br> 3.子線程運行時一定要調用start()方法。<br> 4.在某些特殊情況下在非UI線程是可以更新UI的//不推薦使用(當剛啟動Activity即onCreate里面此時onResume方法還沒有執行的時候可以,因為在線程中更新UI時會調用ViewParent.invalidateChild()方法檢查當前的Thread是否是UIThread,若為UIThread則可以更新(ViewParent是一個接口類,其實現是ViewRootImpl;invalidateChild()方法調用checkThread()方法來檢查線程是否為主線程)。ViewRootImp是在onResume方法中初始化的,所以只要在ViewRootImpl創建之前更新UI(在onCreate方法中創建線程并執行,此時還沒有初始化ViewRootImp),就可以逃避掉checkThread()的檢查進而更新UI。)<br> 5.更新UI的四種方式:<br> a>使用handler.post方法<br> b>使用handler.sendMessage方法,用hanleMessage方法更新UI。<br> c>用runOnUiThread方法。<br> d>使用view.post方法。<br> 6.HandlerThread本質是子線程,在創建子線程的handler時綁定的是handlerThread對象的getLooper()。
查看全部 -
---摘自評論區 ? 在ViewRootImpl沒有實例化的時候是不會check是否是主線程,也就是說,在非UI線程中是可以更新UI的,但是為了線程安全的原因,系統會強制要求只能在主線程中更新UI(猜測)。之所以說沒有太大的意義是因為實際開發中是不會有這種情況的,谷歌官方也是說了只能在UI線程更新UI,這頂多算是一個BUG吧,看不懂的朋友們知道就行了,不用深究~ 非UI線程能否更新UI
非UI線程能否更新UI --->剛啟動的時候,立即在非UI線程更新->不報錯。 --->休眠2s鐘以后,更新——————>報錯 更新UI-->會調用checkForRelayout()方法 -->invalidate()方法-->invalidate(true)方法,關注viewParent-->ViewRootImpl是ViewParent的實現類 --->p.invalidateChild()-->查看ViewRootImpl.invalidateChild()-->checkThread()方法-->判斷UI線程是否是當前線程,不想等拋出異常。 ViewRootImpl是onResume()方法才會創建。所以onCreate()方法中要延遲才可以。 handleResumeActivity()方法---》viewManager.addView()-->ViewRootImpl初始化。,關注viewParent-->ViewRootImpl是ViewParent的實現類
查看全部 -
Android中更新UI的幾種方式: 1.? public?void?activityUpdateUI(){ ??runOnUiThread(new?Runnable()?{ ?????@Override ?????public?void?run()?{ ?????????textView.setText("Changed?by?Activity"); ?????} ??}); } 2.? public?void?handlerChangeUI(){ ??handler.post(new?Runnable(){ ?????@Override ?????public?void?run()?{ ????????textView.setText("OK"); ?????} ??}); } 3.? public?void?handlerChangeUI2(){ ???handler.sendEmptyMessage(1); } 4.?view.post() public?void?viewUpdateUI(){ ??textView.post(new?Runnable()?{ ?????@Override ?????public?void?run()?{ ???????textView.setText("UI?was?updated?by?view.post"); ?????} ??}); } 通過源碼我們可以發現: handler使用post()去發送一個Runnable,其實它內部也是封裝了Message去發送的,本質上和直接發送Message沒有區別; runOnUiThread()方法會判斷當前線程是不是UI線程,不是的話,則調用Activity自己的Handler對象,通過該對象發送一個Runnable;如果是,則調用UI線程的run()方法。 View的post()方法會判斷?attachInfo?是否為空。如果不為空,則通過?attachInfo?的Handler對象去post一個Runnable對象。如果為空,則調用ViewRootImpl的getRunQueue去拿到一個Handler去post一個Runnable對象。 綜上,更新UI的四種方法,本質上都是通過Handler機制去更新UI的。
查看全部 -
public?class?Main2?extends?Activity?implements?View.OnClickListener?{ ????int?aaa=0; ????Button?button1,button2; ????Handler?handler=new?Handler(){ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????Message?message=new?Message(); ????????????System.out.println("Handler"); ????????????threadHandler.sendMessageDelayed(message,1000); ????????} ????}; ???? ????Handler?threadHandler; ????@Override ????protected?void?onCreate(@Nullable?Bundle?savedInstanceState)?{ ????????super.onCreate(savedInstanceState); ????????setContentView(R.layout.main2); ????????button1=(Button)?findViewById(R.id.button1); ????????button2=(Button)?findViewById(R.id.button2); ????????button1.setOnClickListener(this); ????????button2.setOnClickListener(this); ????????HandlerThread?thread=new?HandlerThread("threadHandler"); ????????thread.start(); ????????threadHandler=new?Handler(thread.getLooper()){ ????????????@Override ????????????public?void?handleMessage(Message?msg)?{ ????????????????Message?message=new?Message(); ????????????????System.out.println("ThreadHandler"); ????????????????aaa++; ????????????????System.out.println(aaa); ????????????????if(aaa<5)?{ ????????????????????handler.sendMessageDelayed(message,?1000); ????????????????} ????????????} ????????}; ????} ????@Override ????public?void?onClick(View?view)?{ ????????switch?(view.getId()){ ????????????case?R.id.button1: ????????????????handler.sendEmptyMessage(1); ????????????????break; ????????????case?R.id.button2: ????????????????handler.removeMessages(0); ????????????????threadHandler.removeMessages(0); ????????????????break; ????????????default: ????????????????break; ????????} ????} }
查看全部 -
public?class?Main?extends?AppCompatActivity?implements?View.OnClickListener{ ????private?TextView?textView; ????private?ImageView?imageView; ????Button?btn; ????Handler?handler=new?Handler(new?Handler.Callback()?{ ????????@Override ????????public?boolean?handleMessage(Message?message)?{ ????????????Toast.makeText(getApplicationContext(),""+222,Toast.LENGTH_SHORT).show(); ????????????return?false; ????????} ????}){ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????super.handleMessage(msg); ????????????textView.setText(msg.obj.toString()); ????????????Toast.makeText(getApplicationContext(),""+111,Toast.LENGTH_SHORT).show(); ????????} ????}; ????private?int?imagesId[]={R.drawable.hy1,R.drawable.hy2,R.drawable.hy3}; ????private?MyRunnable?myRunnable=new?MyRunnable(); ????int?index; ????@Override ????public?void?onClick(View?view)?{ ????????handler.removeCallbacks(myRunnable); ????} ????class?Person{ ????????public?int?age; ????????public?String?name; ????????@NonNull ????????@Override ????????public?String?toString()?{ ????????????return?"age:"+age+"?name:"+name; ????????} ????} ????class?MyRunnable?implements?Runnable?{ ????????@Override ????????public?void?run()?{ ????????????index++; ????????????index=index%3; ????????????imageView.setImageResource(imagesId[index]); ????????????handler.postDelayed(myRunnable,1000); ????????} ????} ???? ????@Override ????protected?void?onCreate(@Nullable?Bundle?savedInstanceState)?{ ????????super.onCreate(savedInstanceState); ????????setContentView(R.layout.activity_main); ????????textView=(TextView)?findViewById(R.id.tv); ????????textView.setText("hh"); ????????imageView=(ImageView)?findViewById(R.id.imageView); ????????btn=(Button)findViewById(R.id.button); ????????btn.setOnClickListener(this); ????????handler.postDelayed(myRunnable,1000); ????????new?Thread(){ ????????????@Override ????????????public?void?run()?{ ????????????????super.run(); ????????????????try?{ ????????????????????Thread.sleep(1000); ????????????????????handler.post(new?Runnable()?{ ????????????????????????@Override ????????????????????????public?void?run()?{ ????????????????????????????/*textView.setText("爺"); ????????????????????????????handler.sendEmptyMessage(1);*/ ????????????????????????} ????????????????????}); ????????????????}?catch?(InterruptedException?e)?{ ????????????????????e.printStackTrace(); ????????????????} ????????????????Person?person=new?Person(); ????????????????person.age=18; ????????????????person.name="爺"; ????????????????Message?message=handler.obtainMessage(); ????????????????message.obj=person; ????????????????message.sendToTarget(); ????????????} ????????}.start(); ????} }
查看全部 -
new?Thread()?{ public?void?run()?{ try?{ Thread.sleep(1000); handler.post(new?Runnable()?{ ????????????????@Override public?void?run()?{ ????????//?TODO?Auto-generated?method?stub ????????//?更新文本信息 ????????//?此時直接在這里更新ui的時候,程序將會直接崩潰掉 ????????textView.setText("更新了"); ????????} ????????}); ?????????}?catch?(InterruptedException?e)?{ ????????//?TODO?Auto-generated?catch?block ????????e.printStackTrace(); ?????????} ????????}; }.start(); 從上面的方法中我們可以知道,如果想直接更新ui,我們需要在Thread的run方法中通過 handler.post()的方法來實現,而post方法中的參數是一個new?Runnable(){public?void?run(){} ,然后我們在這個run方法中去更新ui,這才是正確的方法
查看全部 -
handler原理圖解:
查看全部 -
handler原理:
查看全部 -
ViewRootImpl是在WindowManagerGlobal類中的
查看全部 -
ActivityThread中
查看全部 -
checkThread()
查看全部 -
View的invalidateChild(View child)
查看全部 -
View的invalidate方法源碼
查看全部
舉報