该组件的功能是实现文件下载时的进度显示,效果图如下:
代码:
package diy.ts.wader.widget;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MyDownLoadProgressDailog extends AlertDialog {
private ProgressBar mProgress;
private TextView mProgressNum;
private TextView mProgressPercent;
public static final int M = 1024 * 1024;
public static final int K = 1024;
private double dMax;
private double dProgress;
private int middle = K;
private int prev = 0;
private Handler mViewUpdateHandler;
private static final NumberFormat nf = NumberFormat.getPercentInstance();
private static final DecimalFormat df = new DecimalFormat("###.##");
public MyDownLoadProgressDailog(Context context) {
super(context);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getContext());
mViewUpdateHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
double percent = dProgress / dMax;
if (prev != (int) (percent * 100)) {
mProgress.setProgress((int) (percent * 100));
mProgressNum.setText(df.format(dProgress) + "/"
+ df.format(dMax) + (middle == K ? "K" : "M"));
mProgressPercent.setText(nf.format(percent));
prev = (int) (percent * 100);
}
if (mProgress.getProgress() == 100) {
mProgressPercent.setText(nf.format(1));
}
}
};
View view = inflater.inflate(R.layout.download_progress_dialog_layout,
null);
mProgress = (ProgressBar) view.findViewById(R.id.progressbar);
mProgressNum = (TextView) view.findViewById(R.id.progress_num);
mProgressPercent = (TextView) view.findViewById(R.id.progress_percent);
setView(view);
onProgressChanged();
super.onCreate(savedInstanceState);
}
private void onProgressChanged() {
mViewUpdateHandler.sendEmptyMessage(0);
}
public double getDMax() {
return dMax;
}
public void setDMax(double max) {
if (max > M) {
middle = M;
} else {
middle = K;
}
dMax = max / middle;
}
public double getDProgress() {
return dProgress;
}
public void setDProgress(double progress) {
dProgress = progress / middle;
onProgressChanged();
}
}
注:上图中的效果是通过线程来模拟的,而实际运用时,我们通常会启用一个线程或一个异步任务来完成文件下载。下面是一个异步任务类得例子,有关异步任务的知识大家可以参考开发文档。
class TerminalDownLoadTask extends AsyncTask<Void, Integer, Boolean> {
private DownloadProgressDialog progressDialog;
private Handler handler;
private String downLoadUrl;
private boolean flag = false;
public DownLoadTask(int fileSize, Context context,
Handler handler, String url) {
this.handler = handler;
this.downLoadUrl = url;
progressDialog = new DownloadProgressDialog(context);
progressDialog.setTitle("文件下载");
progressDialog.show();
progressDialog.setDMax(fileSize);
}
@Override
protected Boolean doInBackground(Void... params) {
return downLoad();
}
@Override
protected void onProgressUpdate(Integer... progress) {
progressDialog.setDProgress(progress[0]);
}
@Override
protected void onPostExecute(Boolean result) {
progressDialog.dismiss();
Message msg = new Message();
if (result)
msg.what = 1;
handler.sendMessage(msg);
}
private Boolean downLoad() {
URL url = null;
try {
url = new URL(Constants.baseUrl + apkUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
InputStream in = con.getInputStream();
File fileOut = new File(Constants.APK_PATH);
FileOutputStream out = new FileOutputStream(fileOut);
byte[] bytes = new byte[1024];
int c;
int count = 0;
while ((c = in.read(bytes)) != -1) {
out.write(bytes, 0, c);
if (c < 1024) {
publishProgress(count * 1024 + c);
} else {
count++;
publishProgress(count * 1024);
}
}
in.close();
out.close();
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
}
说明:
(1)publishProgress方法会自动调用onProgressUpdate方法并将参数传递过去。而onProgressUpdate方法又会调用自定义组件(MyDownLoadProgressDialog)的setDProgress来刷新进度数据。
(2)DownLoadTask(int fileSize, Context context,Handler handler, String url) 构造方法参数说明:
fileSize: 文件大小,整型且单位是b(byte),用来做被除数计算下载进度。
context: 上下文对象,创建组件实例时要用到。
handler: 用于与主线程通信,通知主线程文件是否下载成功。
url: 文件下载地址。