Android Handler使用案例详解

 更新时间:2021年08月27日 16:11:48   作者:安辉就是我  
这篇文章主要介绍了Android Handler使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

什么是Handler?

Handler可以发送和处理消息对象或Runnable对象,这些消息对象和Runnable对象与一个线程相关联。每个Handler的实例都关联了一个线程和线程的消息队列。当创建了一个Handler对象时,一个线程或消息队列同时也被创建,该Handler对象将发送和处理这些消息或Runnable对象。

handler类有两种主要用途:

  • 执行Runnable对象,还可以设置延迟。
  • 两个线程之间发送消息,主要用来给主线程发送消息更新UI。

为什么要用Handler

解决多线程并发问题,假设如果在一个activity中,有多个线程去更新ui,并且都没有加锁机制,那界面显示肯定会不正常。于是andoird官方就封装了一套更新ui的机制,也可以用handler来实现多个线程之间的消息发送。

如何使用Handler

handler常用的方法有以下这些:

post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable,long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)

我们可以看到这些方法主要分为两类,一种是传入一个Runnable对象,一种是传入一个Message对象。

用代码来学习post一个Runnable对象

先创建Handler对象,直接new一个就行

private Handler handler=new Handler();

实现Runnable接口,用匿名实现方式,重写run方法,就打印一个字符串。

private Runnable runnable=new Runnable() {
        @Override
        public void run() {
            Log.i("MainActivity","Handler Runnable");
        }
};

然后我们调用handler的post方法,这里需要注意的是,post一个Runnable对象,底层用的是回调,不会开启一个新的线程,所有Runnable的run方法还是在主线程里面。是可以更新UI的。

handler.post(runnable);//执行
handler.postDelayed(runnable,2000);//延迟2秒后执行

运行程序,控制台打印的log如下:

05-18 19:17:14.901 17750-17750/com.ansen.handler I/MainActivity: Handler Runnable
05-18 19:17:16.901 17750-17750/com.ansen.handler I/MainActivity: Handler Runnable

从上面的log我们可以看到两条Log的时间相差两秒。这是因为我们用postDelayed方法的时候第二个参数设置了两秒的延迟。

使用sendMessage方法传递消息

从方法的名字上我们可以理解用来发送消息,这个方法在android中使用频率比较高,因为在Android中多线程中是不能更新UI的,必须要通过Handler把消息传递给UI线程,才能更新UI。当然也可以用Handler来两个子线程发送消息。

我们给activity_main文件中TextView控件设置一个id,然后在MainActivity中查找这个控件,在多线程的for循环中给TextView赋值。增加后的代码如下:

textview= (TextView) findViewById(R.id.textview);
new Thread(new Runnable(){
    @Override
    public void run(){
        for(int i=1;i<=100;i++){
            Log.i("MainActivity","当前值是:"+i);
            textview.setText("当前值是:"+i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}).start();

重新运行代码,程序奔溃。控制台打印如下log:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6024)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:820)

这是因为在android中不能在多线程中更新UI造成的。

每个应用启动的时候,Android会启动一个对应的主线程用来处理UI相关的事情,例如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理,所以主线程通常又被叫做UI线程。

这个时候我们就会用到Android的Handle类,Handle可以帮我们解决多线程不能更新UI问题,这里我们只要知道使用这个类就行,在后面我们会详细介绍它的原理。

接下来我们看如何用handler在主线程中接受子线程的消息,并且更新UI。首先new一个Handler的时候实现他的handleMessage方法,修改后的代码如下:

private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        if(msg.what==UPDATE_UI){
            textview.setText("当前值是:"+msg.obj);
        }
    }
};

我们可以看到把更新TextView的代码放到这里来了,并且用到handleMessage的msg参数。这个对象我们常用的一般就两个属性,what就是一个标示,我们发送消息的时候必需要指定值。obj:发送消息的参数。

再来看看多线程的run方法做了哪些改动,首先调用obtainMessage方法,这个方法呢是从消息池里面返回一个Message对象,如果消息池没有才会创建对象,这样避免一直去new Message对象。message对象有what属性是必需要赋值的,是一个int类型。前面我们讲到过了,是一个标示。obj是发送消息用来传参,这里我们传入的是i的值。最后调用handler.sendMessage(message)方法。然后我们handler的handleMessage方法就会回调。

new Thread(new Runnable(){
            @Override
            public void run(){
                for(int i=1;i<=100;i++){
                    Log.i("MainActivity","当前值是:"+i);
                    Message message=handler.obtainMessage();
                    message.what=UPDATE_UI;
                    message.obj=i;
                    handler.sendMessage(message);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
}).start();

还有sendEmptyMessage跟sendMessageDelayed方法我就不一一给大家解释了,有兴趣的朋友自己去实现一下。

源码下载

到此这篇关于Android Handler使用案例详解的文章就介绍到这了,更多相关Android Handler使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android中使用自定义ViewGroup的总结

    Android中使用自定义ViewGroup的总结

    本篇文章主要介绍了Android中使用自定义ViewGroup的总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Android实现TextView中文字链接的4种方式介绍及代码

    Android实现TextView中文字链接的4种方式介绍及代码

    Android实现TextView中文字链接的方式有很多种;总结起来大概有4种:用Spannable或实现它的类,如SpannableString来格式,部分字符串等等,感兴趣的你可以参考下
    2013-02-02
  • Android应用动态修改主题的方法示例

    Android应用动态修改主题的方法示例

    今天小编就为大家分享一篇关于Android应用动态修改主题的方法示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Android开发笔记之Fragment的使用教程

    Android开发笔记之Fragment的使用教程

    我们的Android入门一步步已经进入中级,我们讲完了所有的基本组件的基本使用、Activity、Service、BroadCast,今天我们来介绍一下Fragment的使用教程,需要的朋友可以参考下
    2023-05-05
  • Android Glide图片加载(加载监听、加载动画)

    Android Glide图片加载(加载监听、加载动画)

    这篇文章主要为大家详细介绍了Android Glide图片加载的具体实现方法,包括加载监听、加载动画,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • Android 摄像头高斯模糊的示例代码

    Android 摄像头高斯模糊的示例代码

    本篇文章主要介绍了Android 摄像头高斯模糊的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Android学习小结之获取被启动的Activity传回的数据

    Android学习小结之获取被启动的Activity传回的数据

    这篇文章主要介绍了获取被启动的Activity传回的数据,非常不错,介绍的非常详细,需要的朋友可以参考下
    2016-08-08
  • android实现图片上传功能(springMvc)

    android实现图片上传功能(springMvc)

    这篇文章主要为大家详细介绍了android结合springMvc实现图片上传的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • Android性能优化全局异常处理详情

    Android性能优化全局异常处理详情

    这篇文章主要介绍了Android性能优化全局异常处理详情,文章围绕主题展开详细的内容协商,具有一定的参考价值,感兴趣的小伙伴可以参考一下
    2022-08-08
  • Android实现单选按钮

    Android实现单选按钮

    这篇文章主要为大家详细介绍了Android实现单选按钮,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05

最新评论