但是加到自己的代码中就不能运行,后来发现,自己的代码是在后台运行的,Frontia Demo是在前台运行的。
原因是mCloudStorage.downloadFile()会创建Handler,而创建Handler是需要Looper消息循环来初始化的。如果在自己的子线程中调用mCloudStorage.downloadFile(),这个子线程是没有Lopper消息循环的,自然就创建不了Handler,直接报错:
03-28 12:40:29.120: E/AndroidRuntime(21077): FATAL EXCEPTION: Thread-6094
03-28 12:40:29.120: E/AndroidRuntime(21077): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()03-28 12:40:29.120: E/AndroidRuntime(21077): at com.hugedata.speedometer.AppFileActivity$1LooperThread.run(AppFileActivity.java:152)
也就是说,子线程默认没有Looper,连Handler都创建不了。
解决方法,添加Looper:
注意示例代码中Looper.prepare(); Looper.myLooper().quit(); Looper.loop();这三句的位置:
class LooperThread extends Thread { public void run() { FileUtils.deleteFile(LOCAL_FILE_NAME); Looper.prepare(); final long startTime = System.currentTimeMillis(); //三个参数 mCloudStorage.downloadFile(mFile, new FileProgressListener() { @Override public void onProgress(String source, long allReadedLen, long total) { } }, new FileTransferListener() { @Override public void onSuccess(String source, String newTargetName) { mSuccess = true; synchronized(mFile) { mFile.notify(); } Looper.myLooper().quit(); } @Override public void onFailure(String source, int errCode, String errMsg) { Looper.myLooper().quit(); synchronized(mFile) { mFile.notify(); } mSuccess = false; } }); Looper.loop(); } } private boolean doDownloadFromBaiduCloud() { new LooperThread().start(); synchronized(mFile) { try { mFile.wait(); //这里仅仅借用mFile作为同步锁,无它意 Logger.d("------------------------after wait-----mSuccess:" + mSuccess); } catch (InterruptedException e) { e.printStackTrace(); } }
上面的方式只能执行一次,LooperThread线程退出后,再重新new一个LooperThread执行就会在 mCloudStorage.downloadFile()阻塞,原因是mCloudStorage持有的是用上一个thread 的Looper初始化的,而这个Looper已经quit了,不再looper了!
解决方法:不要每次都new一个LooperThread,全局只要一个就OK,然后自己new一个Handler,所有的任务都post过去,这样就做到了Looper不退出,FrontiaStorage内部new 出的Handler始终跑在这个Looper上:
class LooperThread extends Thread{ private Handler mExecuteHandler = null; public void addTask(Rnnable task){ mExecuteHandler.post(task); } public void run(){ Looper.prepare(); mExeucteHandler = new Handler(); Looper.loop(); } }