activity的深入浅出-------通过几个问题来深入理解handler机制

1.handler的作用是什么

     1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器
     2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面


2.Handle、 Looper 、Message Queue和线程之间的关系

    1).Looper:(相当于隧道) 一个线程可以产生一个Looper 对象,由它来管理此线程里的Message Queue( 车队,消息隧道) 。

    2).Handler: 你可以构造Handler 对象来与Looper 沟通,以便push 新消息到Message Queue 里;或者接收Looper( 从Message Queue 取出) 所送来的消息。

    3). Message Queue( 消息队列): 用来存放线程放入的消息。

    4 ).线程:UI thread 通常就是main thread ,而Android 启动程序时会替它建立一个Message Queue 。

每一个线程里可含有一个Looper 对象以及一个MessageQueue 数据结构。在你的应用程序里,可以定义Handler 的子类别来接收Looper 所送出的消息。


3.主线程里面定义两个不同的handler实例,其中一个handler发出的消息另外一个能接收到吗?

    不能,虽然主线程共享同一个消息队列,但是它们通过message的what变量来区分到底是由哪一个handler发出的消息。Handler实例与消息处理是关联的,发送和接收要匹配

               
              mainHandler2 = new Handler(){

            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.handleMessage(msg);//这里接收不到
                Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler2 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show()  ;
            }
            
        } ;
        mainHandler1 = new Handler(){

            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.handleMessage(msg);//这里能接收到
                Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler1 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show()  ;
            }
            
        } ;

        //Handler Lab1
        findViewById(R.id.buttonHandlerLab1).setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                new Thread(new Runnable(){

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        
                        mainHandler1.sendMessage(defineNewMessage("Lab1")) ;
                        //try to use mainHanlder2 to send meesage and receive .
                        //mainHandler2.sendMessage(defineNewMessage("Lab1")) ;
                        
                    }
                    
                }).start() ;
            }
            
        }) ;

4.任何一个线程都有消息队列吗
     默认只有主线程才有消息队列,自己新建的普通线程是没有线程队列的。不过子线程中用HandlerThread,默认有消息队列

  1)//下面代码会抛出Can't create handler inside thread that has not called Looper.prepare()异常

            findViewById(R.id.buttonHandlerLab2).setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                new Thread(new Runnable(){

                    @Override
                    public void run() {
                        Handler lab2Handler = new Handler()  ;
                        lab2Handler.sendMessage(defineNewMessage("Lab2")) ;
                                              
                    }
                    
                }).start() ;
            }
        }) ;



   2)下面的代码是正确的

              

       class SubHandlerThread extends HandlerThread{

        public SubHandlerThread(String name) {
            super(name);
            // TODO Auto-generated constructor stub
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            ProcessCaculate() ;
            Looper lp = this.getLooper() ;

            new Handler(lp){
                
                @Override
                public void handleMessage(Message msg) {
                    // TODO Auto-generated method stub
                    super.handleMessage(msg);
                    Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message by HandlerThread "+ msg.getData().getString(HANDLER_KEY))  ;
                }
                
            }.sendMessage(defineNewMessage("Lab2.2"))  ;
        }
        
    }







              findViewById(R.id.buttonHandlerLab3).setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stub//using HandlerThread to make handler (message queue) ,send messageSubHandlerThread subHandlerThread = new SubHandlerThread("threadone");  subHandlerThread.start();}}) ;



5.子线程的handler可以使用主线程的消息队列吗
   可以的。

//Handler Lab3.1 child thread get main thread's looper and send message .
        findViewById(R.id.buttonHandlerLab4).setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                new Thread(new Runnable(){
                    
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        Handler lab3Handler  ;
                        lab3Handler = new Handler(Looper.getMainLooper())
                        {

                            @Override
                            public void handleMessage(Message msg) {
                                // TODO Auto-generated method stub
                                super.handleMessage(msg);
                                Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message: "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler")  ;
                            }
                            
                        };
                        lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
                        
                    }
                    
                }).start() ;
            }
            
        }) ;



5.子线程的handler可以使用子线程的消息队列吗



//Handler Lab3.2 using looper.prepare() and looper.loop()  .
        findViewById(R.id.buttonHandlerLab5).setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                new Thread(new Runnable(){
                    
                    @Override
                    public void run() {
                        Looper.prepare();//实例化looper对象,生成消息队列
                        lab3Handler = new Handler(){

                            @Override
                            public void handleMessage(Message msg) {
                                // TODO Auto-generated method stub
                                super.handleMessage(msg);
                                Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message from "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler")  ;
                            }
                        } ;
                        
                        lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
                        Looper.loop() ;//循环消息队列
                    }
                    
                }).start() ;
            }
            
        }) ;


 

总结:
    1.Handler实例与消息处理是关联的,发送和接收要匹配。
    2.Handler操作队列,主要是在子线程操作主线程消息队列
    3.子线程默认是没有消息队列的

你可能感兴趣的:(activity的深入浅出)