zoukankan      html  css  js  c++  java
  • handler机制

    handler机制的一个引子

    在android系统当中,有一个非常重要的铁律,在UI线程之外,是不能修改UI的,在后台线程,新起一个线程,得到的数据结果是不能直接反映在UI上的。
    MainThread (UI线程或主线程)和 WorkrThread (除了主线程之外的其他的线程都叫workThread,对一些可能产生阻塞的操作要放在workthread中完成)
    workthread从原则上来讲是不允许操作UI的,个别控件除外(ProgressBar)
    在一个应用程序当中,UI线程通常用于接收用户的界面输入以及将运算结果反馈给用户

    一个问题,workThread中运算,结果无法反馈到UI,又不能把运算的过程放在主线程中,就产生了workThread和mainThread通讯的问题。

    handle机制就是解决这一问题的

    什么是handler,handler消息处理机制:

    handler就是一个消息处理器,handler,looper(循环器),messageQueue 所构成的这样的一个系统,是android系统当中最重要的消息传递,以及消息处理机制。
    handler负责把消息对象加入到消息队列当中去,looper(循环器)负责把消息对象从消息队列当中取出。handler负责放,looper负责从消息队列中往外取。
    如果消息队列中没有消息对象,那么负责取出消息对象的LOOP的这行代码就会产生阻塞(处于等待的状态),looper把消息对象从消息队列中取出来之后干什么呢?
    looper将会调用handler的handlerMessage方法来处理message对象

    主线程中 Handler A发了一个消息,Handler B在主线程中能不能接收到这个消息呢?一个handler的实例只能接受到自己发的message的信息,

    很多handler共享的是一个messageQueue,通过Message 的what的属性来进行标的,只能收到自己handler相关的message

    主线程有一个Looper,是一个死循环,监听消息队列,但又不是额外的线程,但是不会阻塞主线程,Looper由系统来控制的,底层的vm来控制的

    并非每个线程都有Looper的实例

    handler类的主要作用有两个:

    在新启动的线程中发送消息,在主线程中获取、处理消息。
    每个线程只拥有一个Looper,loop方法负责读取消息队列中的消息,读到信息之后就把消息交给发送该消息的handler处理

    在UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建handler即可,然后通过handler发送处理消息
    程序员自己启动的子线程,程序员需要自己创建一个Looper对象,用prepare方法创建looper对象。


    示例1(从workThread向mainThread发消息)

    public class MainActivity extends Activity {

      private TextView textView;
      private Button button;
      private Handler handler;
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView)findViewById(R.id.textviewId);
        button = (Button)findViewById(R.id.buttonId);
        button.setOnClickListener(new ButtonListener());
        handler = new MyHandler();
      }
      class ButtonListener implements OnClickListener {

        @Override
        public void onClick(View v) {
          Thread thread = new NetWorkThread();
          thread.start();
        }
      }

      class NetWorkThread extends Thread {
        @Override
        public void run() {
          try {
            Thread.sleep( 2 * 1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          String string = "从网络测获取的数据";
          Message msgMessage = handler.obtainMessage();
          msgMessage.obj = string;
          //sendmessage方法无论在主线程中还是workthread中都是可以发送的
          handler.sendMessage(msgMessage);
        }
      }

      class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
          String string = (String)msg.obj;
          //在主线程中就可以随意的操作UI了
          textView.setText(string);
        }
      }
    }

    示例2(从mainThread向workThread发消息,在workThread中生成handler对象)

    public class MainActivity extends Activity {

      private Handler handler;
      private Button button;
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button)findViewById(R.id.buttonId);
        button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            Message msg = handler.obtainMessage();
            handler.sendMessage(msg);
          }
        });
        WorkerThread wtThread = new WorkerThread();
        wtThread.start();
      }

      class WorkerThread extends Thread {
        @Override
        public void run() {
          //准备Looper对象
          Looper.prepare();
          //在workThread当中生成一个handler对象
          handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
              System.out.println("收到了消息对象");
            }
          };
          //调用Loop()方法之后,Looper对象不断的从消息队列当中取出消息对象,然后调用handler的handleMessage方法
          //处理消息对象,如果消息队列当中没有消息对象,则线程阻塞
          Looper.loop();
        }
      }

          LOOPER是由系统控制的,底层实现的,不阻塞主线程

          HandlerThread类有Looper对象,不需要prepare
    }

  • 相关阅读:
    51Nod1740 蜂巢迷宫
    51Nod1279 扔盘子
    51Nod1095 Anigram单词
    51Nod1094 和为k的连续区间
    51Nod1072 威佐夫游戏
    PHP 图片处理
    ubuntu 安装 ftp
    linux下ab网站压力测试命令
    iptables FOr linux
    discuz 个性化时间函数
  • 原文地址:https://www.cnblogs.com/zhangkefan/p/4516218.html
Copyright © 2011-2022 走看看