您的位置:首页 > 运维架构

CountDownTimer 导致的一个崩溃 (Can't create handler inside thread that has not called Looper.prepare())

2017-11-21 10:57 519 查看
Section1  现象
new Thread(new Runnable() {
@Override
public void run() {
new CountDownTimer(10000, 1000) {
@Override
public void onTick(long l) {

}

@Override
public void onFinish() {

}
}.start();
}
}).start();以上代码会导致: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()====================================================Section2 原因原因:查看CountDonwTimer的源码的最后面我们可以看到: // handles counting downprivate Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {synchronized (CountDownTimer.this) {if (mCancelled) {return;}final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();if (millisLeft <= 0) {onFinish();} else if (millisLeft < mCountdownInterval) {// no tick, just delay until donesendMessageDelayed(obtainMessage(MSG), millisLeft);} else {long lastTickStart = SystemClock.elapsedRealtime();onTick(millisLeft);// take into account user's onTick taking time to executelong delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();// special case: user's onTick took more than interval to// complete, skip to next intervalwhile (delay < 0) delay += mCountdownInterval;sendMessageDelayed(obtainMessage(MSG), delay);}}}};}
也就是说CountDownTimer 内部有一个随着对象初始化的成员变量handler,所以如果在没有Looper Prepare 的线程new 一个 CountDownTimer ,自然会有上述错误。
Section3 回调线程
===================================
测试回调线程
new CountDownTimer(5000, 1000) {
@Override
public void onTick(long l) {
Log.i("MainActivity","l==>"+l+"ThreadName==>"+Thread.currentThread().getName());
}

@Override
public void onFinish() {
Log.i("MainActivity","finish==>"+"ThreadName==>"+Thread.currentThread().getName());

}
}.start();
打印结果如下:
12-14 10:52:34.504 3824-3824/com.example.administrator.myapplication I/MainActivity: l==>4935ThreadName==>main
12-14 10:52:35.504 3824-3824/com.example.administrator.myapplication I/MainActivity: l==>3935ThreadName==>main
12-14 10:52:36.505 3824-3824/com.example.administrator.myapplication I/MainActivity: l==>2933ThreadName==>main
12-14 10:52:37.506 3824-3824/com.example.administrator.myapplication I/MainActivity: l==>1932ThreadName==>main
12-14 10:52:39.439 3824-3824/com.example.administrator.myapplication I/MainActivity: finish==>ThreadName==>main
结论
==================================================================================
我们做出如下结论:
1.CountDownTimer 内部有new Handler 的逻辑,所以需要在主线程或者在Looper prepare 之后的线程中调用
2.CountDownTimer 的回调最终也是在其调用线程。
后记这个破bug,耽误了我好几个小时,updateExperimentResult() 这个方法回调会在子线程,而我在回调里面开了timer,但是开timer这个地方又有别的地方会调用。。
所以我一直以为是别地地方的问题。。。
改别人的代码,真是坑。。。。。。
这种问题,单看的时候比较简单,但是当和各种其他问题交杂在一块的时候,就不是那么容易发现的了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程
相关文章推荐