亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

Android面試常客Handler詳解

難度中級
時長 2小時 0分
學習人數
綜合評分9.30
169人評價 查看評價
9.7 內容實用
9.3 簡潔易懂
8.9 邏輯清晰
  • 截獲Handler要接收的消息

    查看全部
  • Handler 作用:1 更新UI, 2發送消息,處理消息

    查看全部
    0 采集 收起 來源:Handler是什么

    2020-02-25

  • ---轉:
    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的實現類

    ?2


    查看全部
  • 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的。

    http://img1.sycdn.imooc.com//5e3298dd00017e2819201080.jpg

    查看全部
  • 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原理圖解:

    http://img1.sycdn.imooc.com//5e32923c0001430a19201080.jpg

    查看全部
  • handler原理:

    http://img1.sycdn.imooc.com//5e32922000019a0819201080.jpg

    查看全部
  • ViewRootImpl是在WindowManagerGlobal類中的

    查看全部
  • ActivityThread中

    查看全部
  • checkThread()

    查看全部
  • View的invalidateChild(View child)

    查看全部
  • View的invalidate方法源碼

    查看全部

舉報

0/150
提交
取消
老師告訴你能學到什么?
通過本課程,你將學到: 1、什么是Handler 2、如何使用Handler 3、Handler的原理是什么 4、如何定義一個與線程相關的Handler 5、Android更新UI的幾種方式 6、非UI線程真的不能更新UI嗎 7、Handler使用過程中遇到的問題

微信掃碼,參與3人拼團

微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

友情提示:

您好,此課程屬于遷移課程,您已購買該課程,無需重復購買,感謝您對慕課網的支持!