但是加到自己的代码中就不能运行,后来发现,自己的代码是在后台运行的,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 android.os.Handler.<init>(Handler.java:121)
03-28 12:40:29.120: E/AndroidRuntime(21077): at com.baidu.frontia.base.taskqueue.QueuedAsyncTaskHelper.<init>(SourceFile:71)
03-28 12:40:29.120: E/AndroidRuntime(21077): at com.baidu.frontia.base.taskqueue.QueuedAsyncTaskHelper.instance(SourceFile:46)
03-28 12:40:29.120: E/AndroidRuntime(21077): at com.baidu.frontia.module.storage.bcs.FrontiaBCSImpl.downloadFile(SourceFile:133)
03-28 12:40:29.120: E/AndroidRuntime(21077): at com.baidu.frontia.api.FrontiaStorage.downloadFile(Unknown Source)
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();
}
}