下载过程中的错误处理逻辑是:
1. 在DownThread的run方法发现异常,调用sendMessage(int type, int data)创建消息添加到队列中。
@Override public void run() { InputStream is = null; HttpURLConnection conn = null; try { file.seek(start); URL connUrl = new URL(url); conn = (HttpURLConnection) connUrl.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(DownTask.connectTimeout); conn.setRequestProperty("Range", "bytes=" + start + "-" + end); int responseCode = conn.getResponseCode(); Logger.d(TAG, "下载资源的字节范围:" + start + "-" + end); if (start > end) { sendMessage(DownMessage.MSG_SUCCESS, 0); return; } if (responseCode == HttpURLConnection.HTTP_PARTIAL || responseCode == HttpURLConnection.HTTP_OK) { is = new BufferedInputStream(conn.getInputStream(), 8192); byte[] buffer = new byte[204800];// 20K缓存 int len = 0; while ((len = is.read(buffer)) != -1 && running) { file.write(buffer, 0, len); sendMessage(DownMessage.MSG_UPDATE, len); } sendMessage(DownMessage.MSG_SUCCESS, 0); } else { sendMessage(DownMessage.MSG_ERROR, 10); } } catch (IOException ex) { try { sendMessage(DownMessage.MSG_ERROR, 0); } catch (InterruptedException e) { e.printStackTrace(); } ex.printStackTrace(); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { try { sendMessage(DownMessage.MSG_STOP, 0); } catch (InterruptedException e1) { } if (file != null) { try { file.close(); } catch (IOException e) { } } file = null; if (is != null) { try { is.close(); } catch (IOException e) { } } is = null; if (conn != null) conn.disconnect(); conn = null; release(); } }
2. 在DownTask的run方法之while循环中取出队列中的消息并且进行处理。不同类别的消息分别进行不同处理,消息类别有:MSG_SUCCESS, MSG_ERROR, MSG_UPDATE, MSG_STOP等。
DownMessage msg; running = true; while (running) { msg = queue.take(); switch (msg.type) { case DownMessage.MSG_SUCCESS: running = false; if (downListener != null) downListener.onDownFinish(); break; case DownMessage.MSG_UPDATE: if (downListener != null) { downListener.onDownUpdate(msg.data); } break; case DownMessage.MSG_ERROR: running = false; if (downThread != null) { downThread.canleDown(); } notifyDownError(ERROR_UNKNOWN); break; case DownMessage.MSG_STOP: running = false; if (downListener != null) { downListener.onDownPause(); } break; } recyle(msg);
downListener.onDownError因大量使用,所以在提取出来,放在notifyDownError方法中。
/** * 下载出错 * * @param type */ private void notifyDownError(int type) { if (downListener != null) downListener.onDownError(type); }
3. 在DownService中实现OnDownListener接口,在接口方法中调用句柄Handler对象来处理不同类别的消息,处理操作包括更新数据库表,展现Toast提示等。
在启动一个下载任务时,实现OnDownListener接口。
/** * 启动一个下载任务。 * * @param down * @param downTask */ public void launchDownloadTask(final Down down, DownTask downTask) { downListener = new OnDownListener() { @Override public void onDownUpdate(int len) { downHandler.obtainMessage(UPDATE_DOWN, len, 0, down).sendToTarget(); } @Override public void onDownStart(int total) { if (down.getLength() < 1) { down.setLength(total); down.setLengthStr(Formatter.formatFileSize(DownService.this, total)); } } @Override public void onDownFinish() { downHandler.obtainMessage(DOWN_FINISH, down).sendToTarget(); } @Override public void onDownError(int type) { handler.obtainMessage(DOWN_FAIL, type, 0, down).sendToTarget(); } @Override public void onDownPause() { downHandler.obtainMessage(PAUSE_DOWN, down).sendToTarget(); } }; downTask.setOnDownListener(downListener); executorService.execute(downTask); }
例如,处理WIFI断开产生的IO异常逻辑:
wifi断开导致IO异常,创建MSG_ERROR消息,添加到队列中。从队列中取出MSG_ERROR消息并处理:取消DownThread线程,设置running为false以结束while循环,在OnDownListener接口实现类中,调用Handler对象更新数据库表等。