android_基础_Handler使用

121 篇文章 1 订阅

转载自: https://www.10qianwan.com/articledetail/809922.html

Android Handler使用案例详解

什么是handler?handler可以发送和处理消息对象或runnable对象,这些消息对象和runnable对象与一个线程相关联。每个handler的实例都关联了一个线程和线程的消息队列。当创建了

(adsbygoogle = window.adsbygoogle || []).push({});

什么是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方法我就不一一给大家解释了,有兴趣的朋友自己去实现一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值