我的代码都是基于的Android Studio编译器。

一、Handler简介

  1. 主要功能:更新UI、消息处理机制(发送和接收处理消息)     2. 使用Handler的原因:如果不用handler机制更新UI会出现如下异常“Only the original thread that created a view hierarchy can touch its views”


这个异常描述提示的是“不能在非UI线程(非Handler处理UI线程)更新UI”。这是Google参考的windows的消息处理机制。
3. 根本目的:解决多线程并发的问题。假设在一个 Activity中,有多个线程去更新 UI,并且对更新的 UI 的操作进行枷锁处理的话又会产生什么样的问题呢? 那就是性能下降,Handler 通过消息队列,保证了消息处理的先后有序。
Android 提供了一套更新 UI 的机制,只要使用这套机制,所有的更新 UI 的操作都是在主线程中轮询处理。

二、Handler中的几个概念

  1. Message
    消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。
  2. Message Queue
    消息队列,用来存放通过Handler发布的消息,按照先进先出执行,是存储消息的容器。MQ被封装到Looper里面了,不会直接与MQ打交道。
  3. Handler
    Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。
  4. Looper
    循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。
  5. 线程
    UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
    每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

三、Handler原理

1. Handler 封装了消息的发送(主要包括消息发送给谁) Looper:    内部包含一个消息队列也就是 MessageQueue,所有 Handler 发送的消息都走向这个队列。    Looper.loop()方法,就是一个 for 死循环,不断的从 MessageQueue 取消息,如果有消息就处理消息,没有消息就阻塞。2. MessageQueue,就是一个消息队列,可以添加消息,处理消息。3. Handler在构造 Handler 时内部会跟 Looper 进行关联,通过 Looper.myLooper() 获取到 Looper,找到 Looper 也就找到了 MessageQueue。在 Handler 中发送消息,其实是向 MessageQueue 队列中发送消息。


一个线程中只有一个 Looper 实例,一个 MessageQueue 实例,可以有多个 Handler 实例

四、Handler使用

一般 UI 主线程(main thread)中不要执行一些耗时的操作,故常通过创建子线程,在子线程中处理消息这样的耗时操作。

1. Handler调用post()方法
内部调用顺序:Handler的post()—>sendMessageDelayed()—>sendMessageAtTime()

protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    tv = (TextView) findViewById(R.id.tv1);    handler = new Handler();    // 利用Handler在界面不断更新系统时间     new Thread() {        @Override        public void run() {            try {                while (true) {                    Thread.sleep(1000);                    handler.post(new Runnable() {                        @Override                        public void run() {                            SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");                            String time = sdFormat.format(new Date());                            tv.setText(time);                        }                    });                }            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }.start();}

2 .Handler调用postDelayed()方法
类似于照片轮播效果

public class MainActivity extends AppCompatActivity {    private Button button;    private ImageView imageView;    private int imag[] = {R.drawable.weather, R.drawable.world, R.drawable.youtube};    private MyRunnable myRunnable = new MyRunnable();    private Handler handler;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button = (Button) findViewById(R.id.button);        handler = new Handler();        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                // 消息移除                handler.removeCallbacks(myRunnable);            }        });        imageView = (ImageView) findViewById(R.id.imageView);        handler.postDelayed(myRunnable, 1000);    private int index;    private class MyRunnable implements Runnable{        @Override        public void run() {            index++;            index = index % 3;            imageView.setImageResource(imag[index]);            // Handler调用postDelayed()方法            handler.postDelayed(myRunnable, 1000);        }    }}

3 .Handler调用sendMessage()方法

protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    tv = (TextView) findViewById(R.id.tv1);    button = (Button) findViewById(R.id.button);    handler = new Handler(){        @Override        public void handleMessage(Message msg) {            /*//msg的arg1和arg2都是整型 tv.setText("arg1 = " + msg.arg1 + ", arg2 = " + msg.arg2);*/            tv.setText("" + msg.obj);        }    };    new Thread(){        @Override        public void run() {            Message message = new Message();// 自己创建的Message            /*//message的值很少时可以通过arg1和arg2来存放 message.arg1 = 88; message.arg2 = 100;*/            // message发送对象            Person person = new Person(18, "FanFF");            message.obj = person;            handler.sendMessage(message);// 或者message.sendToTarget();        }    }.start();}

4 .Handler传递Callback对象
Callback 用于截获 handler 发送的消息,如果返回 true 就截获成功不会向下传递了。

protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.tv1);        handler = new Handler(new Handler.Callback() {            /**Callback用于截获handler发送的消息 * true -- 截获成功,不会继续向下传递执行了,这里即不会执行void handleMessage * false -- 即会继续执行void handleMessage */            @Override            public boolean handleMessage(Message msg) {                Toast.makeText(MainActivity.this, "Callback boolean handleMessage", Toast.LENGTH_LONG).show();                return false;            }        }){            @Override            public void handleMessage(Message msg) {                Toast.makeText(MainActivity.this, "Handler void handleMessage", Toast.LENGTH_LONG).show();            }        };        button = (Button) findViewById(R.id.button);        button.setOnClickListener(new View.OnClickListener()    {            @Override            public void onClick(View v) {                handler.sendEmptyMessage(0);            }        });}
注意:sendEmptyMessage(int what)里的what参数类似于ID,处理消息的时候用于区分,例如if(msg.what == 0){}else if(msg.what == 1){}

更多相关文章

  1. 浅析Android中的消息机制-解决:Only the original thread that cr
  2. Android异步消息机制之Handler
  3. Android的Handler机制详解3_Looper.looper()不会卡死主线程
  4. android 音效处理 (2)
  5. Android之Handler用法总结
  6. Android开发之消息处理机制(一)——Handler
  7. android 音效处理 (2)
  8. Android异步加载图像小结 (含线程池,缓存方法)
  9. android 面试题集

随机推荐

  1. Android中隐藏顶部状态栏:
  2. 【android】可放大缩小图片位置点击位置
  3. Android -- Wifi连接流程分析
  4. MMS发送流程 Android2.2
  5. android 颜色搭配表
  6. 19个实用的Android开发工具
  7. Android Pmem
  8. Android后台保活,这里有你需要的所有姿势
  9. “tns doctor” “You need to have the
  10. Android 折叠效果示例