Handler异步消息传递机制(二)在子线程中创建Handler

声明:本教程不收取任何费用,欢迎转载,尊重作者劳动成果,不得用于商业用途,侵权必究!!!

目录

一、前言

二、简介

三、在主线程中创建Handler

四、在子线程中创建Handler

五、总结说

1、Handler的创建


系列文章

Handler异步消息传递机制(一)Handler常用基本用法

Handler异步消息传递机制(二)在子线程中创建Handler

Handler异步消息传递机制(三)在主线程、子线程中创建Handler,源码(Android 9.0)解析

Handler异步消息传递机制(四)Handler发送消息流程,源码(Android 9.0)解析

一、前言

上一篇文章我们讲到了Handler消息传递机制的最常见用法,我们在主线程创建了Handler对象,然后在新启动的线程创建一个Message对象,然后借助Handler对象发送出去,之后在Handler的handleMessage()方法中获得刚才发送的Message对象,然后就可以进行UI更新操作了。想了解的可参考Handler异步消息传递机制(一)常用实现方式

二、简介

依稀记得13年的某一天一个新来的Android同事,他说我运行程序出现bug了,报的错误信息为:java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(),你知道怎么解决吗?

因为我有收集bug问题解决方式的习惯,于是我找了找自己的笔记给他发了一个链接。然后没过几秒,又问你知道为什么吗?当时有点懵,因为我完全没有印象。平时也不喜欢去记忆一些东西,除非是刚不久用到的东西才会有所印象吧,所以我的回答是:“ 很久了不是记得很清楚了”。

当时感觉还是挺纳闷的,不就是new Hanlder发送消息吗?于是找了一些资料复习了一下。确实不过即使只是简单new一下,还是有不少地方需要注意的!这也使我以后对技术点的探究逐渐的深入了。

我们先尝试在程序中创建两个Handler对象,一个在主线程中创建,一个在子线程中创建,看会有什么效果?

三、在主线程中创建Handler

详见上篇文章 Handler异步消息传递机制(一)常用实现方式 ,它是典型的在主线程中创建Handler的实例

四、在子线程中创建Handler

我们继续以文章 Handler异步消息传递机制(一)Handler常用实现方式 的demo为例,我们把主线程创建的Hanlder注释掉,然后把 Handler 的创建挪到新启动的子线程中,具体代码如下:

package com.luminal.handler_download;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity {
    private  TextView show_text;
    private String strMsg;
    private Handler handler;

    //在主线程中获取、处理消息
//    private Handler handler = new Handler() {
//        @Override
//        public void handleMessage(Message msg) {
//            switch (msg.what) {
//                case 1://下载成功
//                    strMsg = strMsg +"\n"+ "2、apk下载成功。。。开始自动安装下载好的apk!";
//                    show_text.setText(strMsg);
//                    break;
//                case 2://下载失败
//                    strMsg = strMsg +"\n"+ "apk下载失败!";
//                    show_text.setText(strMsg);
//                    break;
//
//                default:
//                    break;
//            }
//        }
//    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        show_text = (TextView) findViewById(R.id.show_text);

        downloadApkFile();

    }


    /**
     *  下载apk文件
     *  注:Android 6.0以上需要申请读写权限
     */
    private void downloadApkFile() {

        strMsg = "1、开始下载apk。。。";
        show_text.setText(strMsg);

        new Thread() {//在新启动的子线程,调用下载app的代码,并发送消息、反馈结果
            public void run() {

                handler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        switch (msg.what) {
                            case 1://下载成功
                                strMsg = strMsg +"\n"+ "2、apk下载成功。。。开始自动安装下载好的apk!";
                                show_text.setText(strMsg);
                                break;
                            case 2://下载失败
                                strMsg = strMsg +"\n"+ "apk下载失败!";
                                show_text.setText(strMsg);
                                break;

                            default:
                                break;
                        }
                    }
                };


                DownLoadAppFile downLoadFile = new DownLoadAppFile();
                downLoadFile.download(null, handler, null);

            };
        }.start();
    }
}

然后运行程序,你会发现,在子线程中创建的Handler是会导致程序崩溃的,提示的错误信息如下:

   java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
        at android.os.Handler.<init>(Handler.java:200)
        at android.os.Handler.<init>(Handler.java:114)
        at com.luminal.handler_download.MainActivity$1$1.<init>(MainActivity.java:60)
        at com.luminal.handler_download.MainActivity$1.run(MainActivity.java:60)

报错信息为:java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(),具体指向代码错误第60行,创建Handler的语句:handler = new Handler() 

英文直译下,不能在没有调用 Looper.prepare() 的线程中创建Handler,那我们试试在线程中先调用一下Looper.prepare(),再创建Handler对象。

                Looper.prepare();
                handler = new Handler() {
                。。。。。。

然后再运行一下程序,果然这样就不会崩溃了,你会发现bug就这么神奇的解决了,但是这时候UI不能更新了!

那么为什么子线程不调用 Looper.prepare() 就创建Handler会报错呢?子线程调用了Looper.prepare()、创建Handler以后,UI界面如何更新呢?欲知故事如何,请看下篇文章的整理分解吧!

五、总结说

1、Handler的创建

(1)一般在主线程中创建Handler

(2)在子线程创建Handler会报错,错误信息为:java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() ,意思是不能在没有调用 Looper的prepare方法的线程中创建Handler,所以我们先要调用Looper的prepare方法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

被开发耽误的大厨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值