精华内容
下载资源
问答
  • 如何在子线程创建并使用Handler

    千次阅读 2019-02-20 17:45:42
    上一篇文章我们从源代码的角度分析了Handler的实现,这篇文章我们说下如何在子线程创建Handler在子线程创建Handler只需2步: 创建looper:Looper.prepare() 启动looper:Looper.loop() 为了创建当前...

    上一篇文章我们从源代码的角度分析了Handler的实现,这篇文章我们说下如何在子线程中创建Handler,在子线程中创建Handler只需2步:

    1. 创建looper:Looper.prepare()
    2. 启动looper:Looper.loop()

    为了创建当前Thread的Handler对外提供一个方法获取当前的Looper,

    Java代码如下:

    public class HandlerThread extends Thread {
    
        private Looper mLooper;
    
        @Override
        public void run() {
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
            }
            Looper.loop();
        }
    
        public Looper getLooper() throws Exception {
            if (!isAlive()) {
                throw new Exception("current thread is not alive");
            }
            if (mLooper == null) {
                throw new Exception("current thread is not start");
            }
            return mLooper;
        }
    }
    

    下面我们来使用下看看:

    class MainActivity : AppCompatActivity() {
        
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val handlerThread = com.example.handlerdemo.HandlerThread()
            handlerThread.start()
            val handler1 = object : Handler(handlerThread.getLooper()) {
                override fun handleMessage(msg: Message?) {
                    super.handleMessage(msg)
                    Log.d("aaa", "thread:${Thread.currentThread().name},handle message")
                }
            }
    
            handler1.sendMessage(Message.obtain())
        }
        
    }
    

    上面的代码非常简单就是创建HandlerThread并start,然后通过HandlerThread的looper创建Handler,发送一条消息进行验证。
    然而我们运行我们会发现直接crash,异常如下:
    在这里插入图片描述
    找到对应的代码我们发现是mLooper未初始化造成的,可我们的代码是先start然后获取的looper,为什么会没有初始化呢?其实这里就是典型的线程同步问题,由于我们启动HandlerThread和创建Handler都是在主线程中运行的,而HandlerThread的run方法是运行在子线程中,所有导致获取looper时HandlerThread还未初始化looper,那么如何解决这个问题呢?

    最简单的解决方案:通过notifyAll和wait

    public class HandlerThread extends Thread {
    
        private Looper mLooper;
    
        @Override
        public void run() {
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Looper.loop();
        }
    
        public Looper getLooper() throws Exception {
            if (!isAlive()) {
                throw new Exception("current thread is not alive");
            }
            synchronized (this){
                if (null == mLooper){
                    wait();
                }
            }
            return mLooper;
        }
    }
    

    在运行,输出日志如下:
    在这里插入图片描述
    我们发现handler处理是在子线程中处理而非主线程。
    其实解决线程同步有很多办法,比如无限循环等待、Semaphore(信号量)等,不过建议使用上面的方式。

    其实SDK已经为我们提供了HandlerThread,我们无需自己来实现,有人可能就说了你这不是蛋疼吗?
    我想说我们不仅仅要会使用SDK提供的api,我们还要学会其中的思想,谁敢说我清楚所有SDK的类和api呢?在开始的时候我真不知道有HandlerThread这个类,然后项目上有需求才实现了这个类,当时我记得很清楚,开始没有注意线程同步的问题,使用的时候才发现的,这个类虽然非常简单,但涉及到非常多的知识,比如Handler的运行原理、线程同步等。
    下面我们看看系统的HandlerThread:
    在这里插入图片描述
    通过这2个构造函数我们发现可以对此线程设置名称和优先级。
    在这里插入图片描述
    与我们的run方法对比多了onLooperPrepared方法,这个方法是让子类重写的。
    我们在看下getLooper方法:
    在这里插入图片描述
    和我自己写的区别主要在synchronized代码块内,区别如下:

    1. 我们是if判断,而系统是while循环判断。
    2. 我们没有在次判断isAlive,而系统判断了。
    3. 未抛出异常,而是直接返回了null。

    我们先想第一个问题是否需要while循环,想想如果用户调用了

    handlerThread.notifyAll();

    那我们将会返回null,显然这不是我们想要的,所以while循环是很必要的,只要looper为null将一直等待。

    第二个问题:上面已经判断了isAlive(),while循环是否需要再次判读,注意wait是挂起操作,如果在挂起的时候用户结束了线程,那么此时线程已经结束了,所以需要判断。

    第三个问题:是抛出异常还是返回null,现在想来个人觉得这2种方法都不是很好,首先返回null,这需要用户处理null的情况,抛出异常在使用上会不太方便,用户需要自己处理异常,使用如下:
    在这里插入图片描述
    需要用户自己try…catch
    不过2选1的话个人认为返回null更好些,不过需要我们使用的时候注意一些。
    继续看HandlerThread源码:

    在这里插入图片描述
    这里提供了一个Handler对象,如果使用了这个Handler,那如何重写handleMessage方法呢?暂时没有想到这个方法的意义在哪?

    继续看:
    在这里插入图片描述
    这里提供了2个退出的方法,这2个方法是looper的方法,这里不再解释了。

    结语:就是这么一个简简单单的功能,可里面涉及到很多方面,在看源码的时候更重要的是学会他们的思想,在看源码的时候可以想想如果是我来写这个功能,我如何来写?千万不要只是想想,不实际动手写,写完后在和系统的对比才会学到更多的东西。

    展开全文
  • 四、在子线程创建Handler 五、总结说 1、Handler的创建 系列文章 Handler异步消息传递机制(一)Handler常用基本用法 Handler异步消息传递机制(二)在子线程创建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方法

     

     

     

     

     

     

     

    展开全文
  • 在子线程创建 handler,要确保子线程有 Looper,UI 线程默认包含 Looper。我们需要用到一个特殊类HandlerThread。这个类可以轻松的创建子线程 handler 创建步骤: 1.创建一个 HandlerThread,即创建一个包含 Looper...

    在子线程中创建 handler,要确保子线程有 Looper,UI 线程默认包含 Looper。我们需要用到一个特殊类HandlerThread。这个类可以轻松的创建子线程 handler

    创建步骤:
    1.创建一个 HandlerThread,即创建一个包含 Looper 的线程HandlerThread 的构造函数有两个

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
    * Constructs a HandlerThread.
    * @param name
    * @param priority The priority to run the thread at. The value supplied must be from
    * {@link android.os.Process} and not from java.lang.Thread.
    */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

    这里我们使用第一个就好:
     

    HandlerThread handlerThread=new HandlerThread("xuan");
    handlerThread.start();//创建 HandlerThread 后一定要记得 start();

    2.通过 HandlerThread 的 getLooper 方法可以获取 Looper
     

    Looper looper=handlerThread.getLooper();

    3.通过 Looper 我们就可以创建子线程的 handler 了
     

    Handlr handler=new Handler(looper);

    通过该 handler 发送消息,就会在子线程执行;
    提示:如果要 handlerThread 停止:

    handlerThread.quit();

    完整测试代码:
     

    HandlerThread hanlerThread = new HandlerThread("子线程");
    hanlerThread.start();
    final Handler handler = new Handler(hanlerThread.getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.d("----->", "线程:" + Thread.currentThread().getName());
        }
    };
    findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            handler.sendEmptyMessage(100);
        }
    });

    像在 intentService(子线程)中,如果要回掉在 UI 线程怎么办呢?
     

    new Handler(getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            // person.getName() Realm objects can only be accessed on the thread they were created.
            Toast.makeText(getApplicationContext(), "Loaded Person from broadcast-receiver->intent-service: " + info, Toast.LENGTH_LONG).show();
        }
    });

     

    展开全文
  • 子线程能创建handler

    2019-11-21 15:36:22
    但是如果你直接使用new thread来创建,代码会报loop的空指针错误,原因如下文,但是,Google给我们提供了HandlerThread,我们当然也可以利用HandlerThread中的思想newThread里面实现子线程创建handler而不报错 ...

    这是之前碰到的一个面试题,准确的来说,子线程是可以创建hanlder的,但是如果你直接使用new thread来创建,代码会报loop的空指针错误,原因如下文,但是,Google给我们提供了HandlerThread,我们当然也可以利用HandlerThread中的思想在newThread里面实现子线程创建handler而不报错

    默认情况下,ActivityThread类为我们创建的了主线程的Looper和消息队列,所以当你创建Handler之后发送消息的时候,消息的轮训和handle都是在ui线程进行的。这种情况属于子线程给主线程发消息,通知主线程更新ui...等,那么反过来,怎么才能让主线程给子线程发消息,通知子线程做一些耗时逻辑??

    Android的消息机制遵循三个步骤:
        1  创建当前线程的Looper  
        2  创建当前线程的Handler 
        3  调用当前线程Looper对象的loop方法

    那么如果我想创建非主线程的Handler并且发送消息、处理消息,这一系列的操作我们应该怎么办?直接上代码:

    public class ChildThreadHandlerActivity extends Activity {
        private MyThread childThread;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_handler);
    
            childThread = new MyThread();
            childThread.start();
    
            Handler childHandler = new Handler(childThread.childLooper){//这样之后,childHandler和childLooper就关联起来了。
                public void handleMessage(Message msg) {
                    
                };
            };
        }
    
        private class MyThread extends Thread{
            public Looper childLooper;
    
            @Override
            public void run() {
                Looper.prepare();//创建与当前线程相关的Looper
                childLooper = Looper.myLooper();//获取当前线程的Looper对象
                Looper.loop();//调用此方法,消息才会循环处理
            }
        }
    }
    

    代码如上,我们依然循序Android的三步走战略,完成了子线程Handler的创建,难道这样创建完了,就可以发消息了么?发的消息在什么线程处理?一系列的问题,怎么办?看代码!!!运行上述代码,我们发现一个问题,就是此代码一会崩溃、一会不崩溃,通过查看日志我们看到崩溃的原因是空指针。谁为空???查到是我们的Looper对象,怎么会那?我不是在子线程的run方法中初始化Looper对象了么?话是没错,但是你要知道,当你statr子线程的时候,虽然子线程的run方法得到执行,但是主线程中代码依然会向下执行,造成空指针的原因是当我们new Handler(childThread.childLooper)的时候,run方法中的Looper对象还没初始化。当然这种情况是随机的,所以造成偶现的崩溃。

    那怎么办?难道我们不能创建子线程Handler ???No!!!No!!!No!!!,你能想到的Android早就为我们实现好了,HandlerThread类就是解决这个问题的关键所在,看代码!!!

    public class HandlerThreadActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_handler);
            TextView textView = (TextView) findViewById(R.id.tv);
            textView.setText("HandlerThreadActivity.class");
    
            HandlerThread handlerThread = new HandlerThread("HandlerThread");
            handlerThread.start();
    
            Handler mHandler = new Handler(handlerThread.getLooper()){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d("HandlerThreadActivity.class","uiThread2------"+Thread.currentThread());//子线程
                }
            };
    
            Log.d("HandlerThreadActivity.class","uiThread1------"+Thread.currentThread());//主线程
            mHandler.sendEmptyMessage(1);
        }
    }
    

    创建HandlerThread对象的时候,有个参数,是指定线程名字的。上面的代码不管运行多少次都不会奔溃!!!并且这种方法创建的handler的handleMessage方法运行在子线程中。所以我们可以在这里处理一些耗时的逻辑。到此我们完成了主线程给子线程发通知,在子线程做耗时逻辑的操作。

    下面我们去看看源码,看看为什么使用HandlerThread就可以避免空指针那?

    public Looper getLooper() {
            if (!isAlive()) {
                return null;
            }
            
            // If the thread has been started, wait until the looper has been created.
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    

    HandlerThread类的getLooper方法如上,我们看到当我们获取当前线程Looper对象的时候,会先判断当前线程是否存活,然后还要判断Looper对象是否为空,都满足之后才会返回给我Looper对象,否则处于等待状态!!既然有等待,那就有唤醒的时候,在那里那???我们发现HandlerThread的run方法中,有如下代码:

    @Override
        public void run() {
            mTid = Process.myTid();
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            Looper.loop();
            mTid = -1;
        }
    

    说明了什么???HandlerThread类start的时候,Looper对象就初始化了,并唤醒之前等待的。所以HandlerThread很好的避免了之前空指针的产生。所以以后要想创建非主线程的Handler时,我们用HandlerThread类提供的Looper对象即可。



    参考作者:_Ricky_
    原文链接:https://www.jianshu.com/p/8abcc4aae6cb

    展开全文
  • 在子线程创建handler的写法: new Thread(new Runnable() { @Override public void run() { //1、准备Looper对象 Looper.prepare(); //2、子线程中创建Handler handler = new Handler() { @...
  • Handler创建子线程Handler Android的消息机制实现步骤: ①创建当前线程的looper ②创建当前线程的handler ③调用当前线程looper的loop方法 要实现创建子线程Handler,按常理应该如此 public class ...
  • 自从开始写代码以来,一直饱受取名之苦,这篇博客实在不知道该给它取个什么名字,总之,...采集用户操作的事件信息,例如某个用户何时采用了何种支付方式购买了何种产品,可以购买成功的回调中将数据信息封装为Ma
  • 主要介绍了Android App在线程创建handler的方法讲解,文中同时讲解了handler和线程的关系以及使用Handler时一些需要注意的地方,需要的朋友可以参考下
  • 子线程创建Handler

    千次阅读 2018-05-08 17:48:35
    我们平时直接创建的Handler实例默认是主线程,是可以直接更新UI操作,而子线程创建的Handler则不可以直接更新UI操作(可以通过runUIThread(Runnable run)切换到主线程),下面介绍两种在子线程创建Handler的方式...
  • 二、为什么子线程不调用Looper.prepare(),创建Handler后会报错呢? 三、主线程中的Handler之前也没有调用Looper.prepare()方法,为什么就没有崩溃呢? 四、总结说 系列文章 Handler异步消息传递机制(一)...
  • newThread(newRunnable(){ publicvoidrun(){ Looper.prepare(); Handlerhandler=newHandler(){ @Override ...
  • Android如何在子线程中使用Handler

    千次阅读 2019-09-16 14:59:23
    在子线程中使用Handler,需要先清楚Handler是如何工作的,这里我画一个简图描述下Handler的工作过程: 这里有提到4个概念: Handler:作为消息的发送和处理者,可以其它线程中使用handler把消息Message存放...
  • Handler消息传递详解,子线程到子线程,主线程到子线程,子线程到主线程 三种消息,Looper,Handler工作机制详解 https://blog.csdn.net/shoneworn/article/details/80447651
  • 分析完上面那篇文章,基本理解了handler的实现原理,乘热打铁,这里我们利用handler原理,在子线程创建一个handler和looper 可能很多面试时候问道,子线程中能不能new一个handler ? 答案是可以的,但是因为主线程系统...
  • Android 子线程创建handler

    千次阅读 2017-12-24 22:55:05
    据上篇我转载的 Handler,Looper, Message 三者关系深入消化,理解后。...但是有人会疑问,那子线程中是否可以创建一个Handler,仅仅通知线程呢? 答案是肯定的。 直接上代码。 new Thread(new Runnable() {
  • Handler handler= new Handler(Looper. myLooper ()){ @Override public void handleMessage (Message msg) { textView .setText(msg. obj + "" ) ; } } ; int i= 0 ; while ( true ){ ...
  • 复习一下消息机制,如下代码: new Thread() { Handler handler = null; [@Override](https://my.oschina.net/u/1162528) public void run() { ...
  • 转载注明出处:http://blog.csdn.net/u010181592/article/category/5893483文章出自 我不只是看客的博客很多人都知道不能直接在子线程new 一个Handler,android会报错,至于为什么会报错,并没有做深入的研究,今天...
  • 如何在子线程创建Handler?

    千次阅读 2015-12-24 17:57:02
    也许大家创建Handler都不陌生,但是如果要在子线程创建Handler,大家未必都能正确, 子线程中创建handler,要确保子线程有Looper,UI线程默认包含Looper 我们需要用到一个特殊类  HandlerThread 这个类可以轻松的...
  • 可是完全也没必要非得在子线程创建Handler实例啊,主线程完全可以完成所有的事情,解决所有的问题,完全可以不去踩这个坑的,你踩过一次坑,别人必须也得踩过才是熟练使用,没踩过就就是大笨蛋? 得出结论:这...
  • 1. 前言众所周知,android中,非ui线程中是不能更新ui,如果在子线程中做ui相关操作,可能会出现程序崩溃。...初始化Handler有两个地方,一个主线程中,一个在子线程中,具体有什么区别呢,接下来
  • 主线程处理handler,大家都比较熟悉了,就是通过onCreat中,new Handler  handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { System.out.println(...
  • 为什么不需要创建 Looper ,就能主线程直接使用 Handler ? 每个Handler线程都有一个 Looper ,主线程当然也不例外,但是我们不曾准备过主线程的 Looper 而可以直接使用,这是为何? 通常我们认为 ...
  • Android子线程创建Handler方法

    万次阅读 2015-01-12 11:11:07
    在子线程创建Handler
  • handler.post运行在子线程

    千次阅读 2019-07-02 10:26:27
    看过一个面试题,问题是handler.post运行子线程吗,很多人回好不思索马上说运行...可以看到handler子线程创建主线程调用handler.post runnable运行的线程id和主线程id不一致,因此此时是运行子线程的。 ...
  • 在子线程中使用Handler

    2020-03-18 16:57:36
    在子线程创建Handler时会抛出RuntimeException异常,提示Can’t create handler inside thread …,这是由于Handler构造时没有找到当前线程的Looper导致的 mLooper = Looper.myLooper(); if (mLooper == null) {...
  • 接触Android一定对Handler不陌生,它是用来处理线程间通信问题。例如如下代码: public class HandlerTestActivity extends Activity { Handler mHandler = new Handler() { @Override public void ...
  • Android多线程(Handler篇)

    万次阅读 多人点赞 2018-06-13 23:09:01
    由于Android中的耗时操作不能放入主线程中...创建Handler对象,实现handlMessage()方法 创建Runnable线程 此时产生一个Looper,并自动创建一个消息队列MessageQueue() Looper轮询MessageQueue交给Handler Handl...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 72,271
精华内容 28,908
关键字:

在子线程创建handler