zoukankan      html  css  js  c++  java
  • Android攻城狮Handler简介

    Handler是什么?
    Handler是Android提供的一套用来更新UI的机制,也是一套消息处理机制,可以通过它发送消息,也可以通过它处理消息。
    所有Activity生命周期回调的方法(例如onCreate()、onDestory()等等),都是通过handler机制去发送消息的,然后根据不同的消息(message)做相应的分支处理。例如发送一个消息给 Framework,告知需要调用onCreate()或onDestory()方法。实际上在 Framework 当中,Activity的交互大部分都是用AMS(Activity Manager Service)做处理的。整个应用程序的核心的一个类就是 Activity Thread,Activity Thread就是通过handler机制接收到 Activity Manager Service发送的有关Activity生命周期的管理的消息(比如启动)。
    
    为什么要使用Handler?
    Android在设计的时候,就封装了一套消息的创建、传递、处理机制,如果不遵循这样的机制,就没有办法更新UI信息,并且会抛出异常信息。这样的机制便包含Handler机制。

    1. 我们要创建一个handler的时候,它会和默认的一个线程进行绑定,而这个默认的线程当中就有一个MessageQueue(消息队列)。
    2. handler的两个用途:(1)定时发送一个Messages或者Runnables对象;(2)可以在一个线程当中去处理并执行一个Action的动作。
    3. 主线程运行一个消息队列,并管理着一些顶级的应用对象(top-level application objects),包括Activity、Broadcast Receiver等等,这些对象默认都是创建在Activity Thread(也就是我们常说的UI线程或者主线程)当中。


    Handler的示例,实现图片轮播。
    代码实现
    1. 在主布局中定义一个ImageView控件。
    2. 在 MainActivity 中创建并初始化ImageView,定义一个图片数组 images 和数组下标索引 index,创建一个Handler对象。
    3. 创建一个内部类 MyRunnable 实现 Runnable 接口,重写 run() 方法:
       public void run() {
           index++;
           index = index%3; // 图片轮播(一般是通过ViewPager实现图片轮播)
           imageView.setImageResource(images[index]);
           handler.postDelayed(myRunnable,1000); // 每隔一秒换一次图片
       }
    4. 在onCreste()方法中调用handler,也就是在主线程中调用handler:
       handler.postDelayed(myRunnable,1000);
      1 public class MainActivity extends ActionBarActivity {
      2      private Handler handler1 = new Handler();
      3     private Handler handler2 = new Handler(new Callback() {
      4 
      5         @Override
      6         public boolean handleMessage(Message msg) {
      7             // TODO Auto-generated method stub
      8             Toast.makeText(getApplicationContext(), "1", 1).show();
      9             return false;// 若设为true则后边不执行
     10         }
     11     }) {
     12 
     13         public void handleMessage(Message msg) {
     14             // TODO Auto-generated method stub
     15             Toast.makeText(getApplicationContext(), "2", 1).show();
     16         }
     17 
     18     };
     19     
     20     
     21     private Handler handler3 = new Handler() {
     22         public void handleMessage(android.os.Message msg) {
     23             // textView.setText(""+msg.arg1+"-"+msg.arg2);
     24             textView.setText("" + msg.obj);
     25         };
     26     };
     27     
     28     
     29     private TextView textView;
     30     private ImageView imageView;
     31     private int Image[] = { R.drawable.a, R.drawable.b, R.drawable.c };
     32     private int index;
     33 
     34     @Override
     35     protected void onCreate(Bundle savedInstanceState) {
     36         super.onCreate(savedInstanceState);
     37         setContentView(R.layout.fragment_main);
     38         textView = (TextView) findViewById(R.id.textview);
     39         imageView = (ImageView) findViewById(R.id.imageView1);
     40         new Thread() {
     41             public void run() {
     42                 try {
     43                     Thread.sleep(2000);
     44                     // (1)
     45                     // Message message=new Message();
     46                     // message.arg1=88;
     47                     // message.arg2=100;
     48 
     49                     // (2)
     50                     Message message = handler3.obtainMessage();
     51 
     52                     Person person = new Person();
     53                     person.age = 23;
     54                     person.name = "zy";
     55                     message.obj = person;
     56                     // handler.sendMessage(message);//(1)
     57                     message.sendToTarget();// (2)
     58 
     59                 } catch (InterruptedException e) {
     60                     // TODO Auto-generated catch block
     61                     e.printStackTrace();
     62                 }
     63             };
     64         }.start();
     65 
     66         /*
     67          * new Thread() { 
     68          * public void run() { 
     69          * try { Thread.sleep(1000);
     70          * handler.post(new Runnable() {
     71          * 
     72          * @Override 
     73          * public void run() {
     74          *  // TODO Auto-generated method stub
     75          * textView.setText("更新线程"); } });
     76          * 
     77          * } catch (InterruptedException e) { // TODO Auto-generated catch block
     78          * e.printStackTrace(); } }; }.start();
     79          */
     80 
     81         handler1.postDelayed(myRunnable, 1000);// 1000:一秒钟换一次
     82 
     83     }
     84 
     85     MyRunnable myRunnable = new MyRunnable();
     86 //图片循环播放
     87     class MyRunnable implements Runnable {
     88 
     89         @Override
     90         public void run() {
     91             // TODO Auto-generated method stub
     92             index++;
     93             index = index % 3;
     94             imageView.setImageResource(Image[index]);
     95             handler1.postDelayed(myRunnable, 1000);
     96         }
     97     }
     98 
     99     class Person {
    100         public int age;
    101         public String name;
    102 
    103         @Override
    104         public String toString() {
    105             // TODO Auto-generated method stub
    106             return "name=" + name + "age=" + age;
    107         }
    108     }
    109 
    110     public void click(View view) {
    111         handler1.removeCallbacks(myRunnable);
    112         handler2.sendEmptyMessage(1);
    113     }
    114 
    115 }
    Android为什么要设计只能通过Handler机制更新UI呢?
    最根本的目的就是解决多线程并发的问题。
    1. 假如在一个Activity当中,有多个线程去更新UI,并且都没有加锁机制,那么会产生什么样子的问题?
    --> 更新界面混乱。
    2. 如果对更新UI的操作都进行加锁处理的话又会产生什么样子的问题?
    --> 性能下降。
    正是对以上问题的考虑,Android给我们提供了一套更新UI的机制,我们只需遵循这样的机制就可以了,根本不用去关心多线程(并发)的问题,所有的更新UI的操作,都是在主线程的消息队列中去“轮询”处理的。
    
    Handler的原理是什么?
    面试经典问题:Looper、Handler、Message(或MessageQueue)三者间的关系?
    一、Handler封装了消息的发送(主要是将消息发送给谁(默认是Handler自己),以及什么时候发送)。
    Looper:
    1.内部包含一个消息队列 MessageQueue,所有的 Handler 发送的消息都走向(加入)这个消息队列。
    2.Looper.Looper方法,就是一个死循环,不断地从 MessageQueue 取得消息,如果有消息就处理消息,没有消息就阻塞。
    二、MessageQueue
    MessageQueue 就是一个消息队列,可以添加消息,并处理消息。
    三、Handler 也很简单,内部会跟 Looper 进行关联,也就是说,在 Handler 的内部可以找到 Looper,找到了 Looper 也就找到了 Message。在 Handler 中发送消息,其实就是向 MessageQueue 队列中发送消息。
    
    总结:Handler 负责发送消息,Looper 负责接收 Handler 发送的消息,并直接把消息回传给 Handler 自己,MessageQueue就是一个存储消息的容器。




  • 相关阅读:
    HTML5 History 模式 nginx配置
    nginx配置及性能调优
    windows启动jar包bat文件
    在线小工具
    BAT文件里Maven命令执行后退出的解决方案
    文字超出隐藏
    SOCKET.IO
    call与apply简单介绍
    html里面,没有内容,要高度占满页面
    css实现三角形标
  • 原文地址:https://www.cnblogs.com/my334420/p/6758396.html
Copyright © 2011-2022 走看看