309_子线程创建Handler





子线程创建Handler


这篇是看郭霖大神博客写的


相当于读书笔记而已


博客地址是:http://blog.csdn.net/guolin_blog/article/details/9991569




一.子线程中不能创建Handler
        new Thread(new Runnable() {
            @Override
            public void run() {
                Handler handler = new Handler();
            }
        }).start();


这样会报错:
Can't create handler inside thread that has not called Looper.prepare()








二.创建之前增加Looper.prepare(); 
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Handler handler = new Handler();
            }
        }).start();








三.为什么要增加Looper.prepare();
看看源码
看看Handler的构造函数
    public Handler() {  
        if (FIND_POTENTIAL_LEAKS) {  
            final Class<? extends Handler> klass = getClass();  
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
                    (klass.getModifiers() & Modifier.STATIC) == 0) {  
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
                    klass.getCanonicalName());  
            }  
        }  
        mLooper = Looper.myLooper();  
        if (mLooper == null) {  
            throw new RuntimeException(  
                "Can't create handler inside thread that has not called Looper.prepare()");  
        }  
        mQueue = mLooper.mQueue;  
        mCallback = null;  
    }  


我们看到先是mLooper = Looper.myLooper();
然后判断如果mLooper为空,就报这个错误








四.为什么会出现mLooper的情况
看看myLooper()这个方法


    public static final Looper myLooper() {  
        return (Looper)sThreadLocal.get();  
    }  


这个方法的意思就是:从sThreadLocal中取出一个Looper
mLooper为空,就说明sThreadLocal里面没有Looper










五.为什么sThreadLocal里面没有Looper
我们来看看Looper的prepare()方法就完全明白了
    public static final void prepare() {  
        if (sThreadLocal.get() != null) {  
            throw new RuntimeException("Only one Looper may be created per thread");  
        }  
        sThreadLocal.set(new Looper());  
    }  


调用prepare方法的时候也是先调用sThreadLocal的get方法
检查一下现在sThreadLocal里面有没有Looper
如果sThreadLocal不为空,那么就报错:一个线程只能有一个Looper
如果sThreadLocal里面还没有Looper,那么就给sThreadLocal设置一个new Looper()








六.为什么主线程不需要prepare
因为程序启动的时候,系统已经自动调用了主线程的Looper.prepare()方法
    public static void main(String[] args) {  
        SamplingProfilerIntegration.start();  
        CloseGuard.setEnabled(false);  
        Environment.initForCurrentUser();  
        EventLogger.setReporter(new EventLoggingReporter());  
        Process.setArgV0("<pre-initialized>");  
        Looper.prepareMainLooper();  
        ActivityThread thread = new ActivityThread();  
        thread.attach(false);  
        if (sMainThreadHandler == null) {  
            sMainThreadHandler = thread.getHandler();  
        }  
        AsyncTask.init();  
        if (false) {  
            Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));  
        }  
        Looper.loop();  
        throw new RuntimeException("Main thread loop unexpectedly exited");  
    }  


里面Looper.prepareMainLooper()就是








七.总结:
主线程已经自动prepare过了,子线程中创建Handler需要prepare.





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值