为了账号安全,请及时绑定邮箱和手机立即绑定

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下载
官方微信
友情提示:

您好,此课程属于迁移课程,您已购买该课程,无需重复购买,感谢您对慕课网的支持!