progressBar说明

在某些操作的进度中的可视指示器,为用户呈现操作的进度,还它有一个次要的进度条,用来显示中间进度,如在流媒体播放的缓冲区的进度。

一个进度条也可不确定其进度。在不确定模式下,进度条显示循环动画。这样的模式经常使用于应用程序使用任务的长度是未知的。

XML重要属性

android:progressBarStyle:默认进度条样式

android:progressBarStyleHorizontal:水平样式

progressBar重要方法

getMax():返回这个进度条的范围的上限

getProgress():返回进度

getSecondaryProgress():返回次要进度

incrementProgressBy(int diff):指定添加的进度

isIndeterminate():指示进度条是否在不确定模式下

setIndeterminate(boolean indeterminate):设置不确定模式下

setVisibility(int v):设置该进度条是否可视

progressBar重要事件

onSizeChanged(int w, int h, int oldw, int oldh):当进度值改变时引发此事件

项目实现步骤分析

1.给进度调设置最大值

2.不管哪一个线程下载都要记录进度条当前位置,并设置值

3.给textview设置显示当前下载值

4.创建暂时文件把曾经下载好的位置记录起来

5.当线程下载完后删除暂时保存进度条位置的文件

主要代码:

加入权限

<uses-permission android:name="android.permission.INTERNET"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

布局文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android_download"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.android_download.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

StreamTools工具

android线程下载的工具一样http://blog.csdn.net/zhaoyazhi2129/article/details/27189465

Activity主要代码

package com.example.android_download;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL; import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast; import com.example.util.StreamTools; public class MainActivity extends Activity {
private int threadNum = 3;// 线程开启的数量
private int threadRunning = 3;// 正在执行的线程
private TextView tv_pb;
private EditText et_url;
private ProgressBar pb_download;
private int currentPb;//当前值 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findView(); File sdDir = Environment.getExternalStorageDirectory();
File pdFile = new File(sdDir, "pb.txt");
InputStream is = null;
try {
// 推断文件是否存在
if (pdFile.exists()) {
is = new FileInputStream(pdFile);
} } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (is != null) {
String value = StreamTools.streamToStr(is);
//拆分
String arr[] = value.split(";"); pb_download.setMax(Integer.valueOf(arr[0]));// 最大值
currentPb = Integer.valueOf(arr[1]);// 当前值
pb_download.setProgress(currentPb);
tv_pb.setText("当前的进度是:"+arr[2]);
}
} /**
*
*/
public void findView() {
tv_pb = (TextView) findViewById(R.id.tv_pb);
et_url = (EditText) findViewById(R.id.et_url);
pb_download = (ProgressBar) findViewById(R.id.pb_download);
} // 下载文件(得到server端的文件大小 )
public void downLoadFile(View v) {
// 获取下载路径
final String spec = et_url.getText().toString();
if (TextUtils.isEmpty(spec)) {
Toast.makeText(this, "下载地址不能为空", 0).show();
} else {
new Thread() {
@Override
public void run() {
// 訪问网络地址
try {
// 依据下载的地址构建url对象
URL url = new URL(spec);
// 通过URL对象的openConnection()方法打开连接,返回一个连接对象
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();
// 设置请求头
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setReadTimeout(5000); // 推断是否响应成功
if (httpURLConnection.getResponseCode() == 200) {
/**
* 第一步:得到server下载文件的大小,然后在本地设置一个暂时文件和server端文件大小一致
*/
// 获取文件长度
int fileLength = httpURLConnection
.getContentLength();
//给进度条设置最大值
pb_download.setMax(fileLength);
//推断SD卡是否可用
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
// 外部存储设备的路径
File sdFile = Environment
.getExternalStorageDirectory();
//获取文件名
String fileName = spec.substring(spec.lastIndexOf("/")+1);
// 随机訪问文件的读取与写入RandomAccessFile(file, mode)
RandomAccessFile accessFile = new RandomAccessFile(
new File(sdFile, fileName), "rwd");
// 设置暂时文件与server文件大小一致
accessFile.setLength(fileLength);
// 关闭暂时文件
accessFile.close(); /**
* 第二步:计算出每一个线程下载的大小(開始位置,结束位置)
*/
// 计算出每一个线程下载的大小
int threadSize = fileLength / threadNum;
// for循环,计算出每一个线程的開始和结束位置
for (int threadId = 1; threadId <= 3; threadId++) {
int startIndex = (threadId - 1) * threadSize;// 開始位置
int endIndex = threadId * threadSize - 1;// 结束位置
if (threadId == threadNum) {// 最后一个 线程
endIndex = fileLength - 1;
} System.out.println("当前线程--" + threadId
+ "-----開始位置" + startIndex + "----结束位置"
+ endIndex + "-----线程大小" + threadSize);
/**
* 第三步:每创建好一次就要开启线程下载
*/
new DownLoadThread(threadId, startIndex,
endIndex, spec,fileName).start(); }
}else {
runOnUiThread(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "SD卡不存在", 1).show();
}
});
}
} else {
runOnUiThread(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "server端返回错误", 1).show();
}
});
} } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start(); }
} /**
* 每创建好一次就要开启线程下载
*
* @author zhaoyazhi
*
*/
class DownLoadThread extends Thread {
// 成员变量
private int threadId;
private int startIndex;
private int endIndex;
private String path;
private String fileName; File sdFile = Environment.getExternalStorageDirectory(); /**
*
* @param threadId
* 线程的序号
* @param startIndex
* 线程下载開始位置
* @param endIndex
* 线程下载结束位置
* @param path
* 线程下载保存文件的路径
*/
public DownLoadThread(int threadId, int startIndex, int endIndex,
String path,String fileName) {
super();
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path;
this.fileName = fileName;
} @Override
public void run() {
// 能够通过每一个线程去下载文件
try {
/**
* 第四步:从本地文件上读取已经下载文件的開始位置
*/
File recordFile = new File(sdFile, threadId + ".txt");
if (recordFile.exists()) {
// 读取文件
InputStream is = new FileInputStream(recordFile);
// 利用工具类转换
String value = StreamTools.streamToStr(is);
// 获取记录的位置
int recordIndex = Integer.parseInt(value);
// 把记录的位置付给開始位置
startIndex = recordIndex;
}
// 通过path对象构造URL 对象
URL url = new URL(path);
// 通过URL对象openConnection
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();
// 设置请求头
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setConnectTimeout(5000);
// 设置下载文件的開始位置和结束位置
httpURLConnection.setRequestProperty("Range", "bytes="
+ startIndex + "-" + endIndex);
// 获取状态码
int code = httpURLConnection.getResponseCode();
// System.out.println(code);
// 推断是否成功 仅仅要设置"Range"头,返回的状态码就是206
if (code == 206) {
// 获取每一个线程返回的流对象
InputStream is = httpURLConnection.getInputStream();
// 创建随机訪问的对象
RandomAccessFile accessFile = new RandomAccessFile(
new File(sdFile, fileName), "rwd");
// 指定開始位置
accessFile.seek(startIndex);
// 定义读取的长度
int len = 0;
// 定义缓冲区
byte buffer[] = new byte[1024*1024];
int total = 0;
// 循环读取
while ((len = is.read(buffer)) != -1) {
System.out.println("当前线程--" + threadId
+ "-----当前下载的位置是" + (startIndex + total));
// 保存每一个线程的下载位置
RandomAccessFile threadFile = new RandomAccessFile(
new File(sdFile, threadId + ".txt"), "rwd");
// 记录每次下载位置
threadFile.writeBytes((startIndex + total) + "");
threadFile.close();
accessFile.write(buffer, 0, len);
total += len;// 已经下载大小 /**
* 当程序有多个线程訪问一个变量。能够用synchronized解决
*/
synchronized (MainActivity.this) {
//进度条当前进度
currentPb += len;
pb_download.setProgress(currentPb);
final String percent= currentPb*100l/pb_download.getMax()+"%";
runOnUiThread(new Runnable() { @Override
public void run() {
//计算百分比操作 tv_pb.setText("当前的进度是:"+percent);
}
});
//创建保存当前 进度和百分比
RandomAccessFile pbFile = new RandomAccessFile(
new File(sdFile, "pb.txt"), "rwd");
pbFile.writeBytes(pb_download.getMax()+";"+currentPb+";"+percent);
pbFile.close();
} }
accessFile.close();
is.close(); runOnUiThread(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "当前线程" + threadId + "---完成下载", 1).show();
}
});
/**
* 第五步:当你的n个线程都完成下载 的时候我才进行删除记录下载位置的缓存文件
*/
deleteRecordFile();
} else {
runOnUiThread(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "server端返回错误", 1).show();
}
});
}
// 设置你下载文件
} catch (Exception e) {
e.printStackTrace();
} } } /**
* synchronized避免线程同步 下载完删除存储文件下载位置的暂时文件
*/
public synchronized void deleteRecordFile() {
// 外部存储设备的路径
File sdFile = Environment.getExternalStorageDirectory();
// 线程下载完就减去
threadRunning--;
// 当没有正在执行的线程
if (threadRunning == 0) {
for (int i = 1; i <= 3; i++) {
File recordFile = (new File(sdFile, i + ".txt"));
if (recordFile.exists()) {
recordFile.delete();
}
File pbFile = (new File(sdFile, "pb.txt"));
if (pbFile.exists()) {
pbFile.delete();
}
} }
} }

补充知识点

不用在给进度条设置值的时候考虑同步。由于android定义progressBar的时候已经 设置了同步

2.当程序有多个线程訪问一个变量,能够用synchronized解决

synchronized (MainActivity.this) {
//进度条当前进度
currentPb += len;
pb_download.setProgress(currentPb); runOnUiThread(new Runnable() { @Override
public void run() {
tv_pb.setText("当前的进度是:"+currentPb*100/pb_download.getMax()+"%");
}
});

执行结果

1.当文件下载时,进度条显示和当前进度显示

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhb3lhemhpMjEyOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

2.当又一次载入时继续上次下载

3.当文件进行下载时,暂时存储下载文件位置的pb.txt被创建

4.当线程完成下载后,在主线程Toast完成下载

5.当下在完毕后进度条走满,当前进度为100%

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhb3lhemhpMjEyOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

6.下载完后,暂时文件销毁

源码下载地址:http://download.csdn.net/detail/zhaoyazhi2129/7406731

转发请标明出处:http://blog.csdn.net/zhaoyazhi2129/article/details/27192169

赵雅智_android多线程下载带进度条的更多相关文章

  1. 赵雅智_Android的getResources()资源引用

    今天做一个Android的刮刮乐项目.里面用到非常多的地方用到了getResources. <span style="font-size:12px;"> // 获得图片 ...

  2. 赵雅智_Android编码规范

    凝视 导入mycodetemplates.xml统一凝视样式 须要加凝视的地方 类凝视(必加) 方法凝视(必加) 块凝视主要是数据结构和算法的描写叙述(必加) 类成员变量和常量凝视(选择性加入) 单行 ...

  3. 赵雅智_Android案例_刮刮乐

    实现效果 主要代码 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  4. 赵雅智_android获取本机运营商,手机号部分能获取

    手机号码不是全部的都能获取.仅仅是有一部分能够拿到. 这个是因为移动运营商没有把手机号码的数据写入到sim卡中.SIM卡仅仅有唯一的编号.供网络与设备 识别那就是IMSI号码,手机的信号也能够说是通过 ...

  5. Java POI 3.17导出EXCEL并下载(带进度条提示)

    导出数据 共4590条 只需要 5 秒左右,性能还算可以 我们再来测试一下 50000 条的性能...

  6. 赵雅智:android教学大纲

    带下划线为详细内容链接地址.点击后可跳转.希望给大家尽一些微薄之力.眼下还在整理中 教学章节 教学内容 学时安排 备注 1 Android高速入门 2 Android模拟器与常见命令 3 Androi ...

  7. android:异步任务asyncTask介绍及异步任务下载图片(带进度条)

    为什么要用异步任务? 在android中仅仅有在主线程才干对ui进行更新操作.而其他线程不能直接对ui进行操作 android本身是一个多线程的操作系统,我们不能把全部的操作都放在主线程中操作 .比方 ...

  8. Android -- 自定义带进度条的按钮

    1. 实现了一个带进度条的按钮,完成后显示提示信息,并设置按钮为不可再次被点击

  9. atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7

    atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7 1. 实现原理 1 2. 大的文件上传原理::使用applet 1 3. 新的bp 2 1. 性能提升---分割小文件上传 ...

随机推荐

  1. Design Pattern Singleton 单一模式

    单一模式的几个注意点: 一) 设计单一模式,首先须要把构造函数给私有化了,不让外界訪问,那么外界仅仅能通过提供的函数获取一个新的类. 二) C++的单一模式,记得要在类外初始化一个类,否则或内存出错的 ...

  2. error: conflicting type qualifiers for &#39;xxxxx&#39;

    网上的非常多解释--非常难理解-- 情景描写叙述: 在代码中,写了A\B两个文件,A:是.c文件,B是.h文件和.c文件. 在A中包括了B.h文件. 在B.h文件里声明了A中定义的变量. 这样编译的情 ...

  3. git打pach包

    在开发中,我们发出的基线版本号常常会有一些bug须要修复,假设採用本地上库,然后再给用户新的版本号,可能会费时费力,而假设给用户我们改动后的代码让用户一行一行合入本地,也显的比較落后,假设用户那边也使 ...

  4. SharePoint 2013 升级

    原文地址:https://www.nothingbutsharepoint.com/sites/devwiki/articles/Pages/SharePoint-2013-Upgrade.aspx ...

  5. P值(P-value),“差异具有显著性”和“具有显著差异”

    郑冰刚提到P值,说P值的定义(着重号是笔者加的,英文是从WikiPedia摘来的): P值就是当原假设为真时,比所得到的样本观察结果更极端的结果出现的概率. The P-value is the pr ...

  6. OpenCV学习(39) OpenCV中的LBP图像

    本章我们学习LBP图像的原理和使用,因为接下来教程我们要使用LBP图像的直方图来进行脸部识别. 参考资料: http://docs.opencv.org/modules/contrib/doc/fac ...

  7. 一款超炫的jquery图片播放插件[Cloud Carousel]

    今天给大家介绍一个jquery图片播放插件,也可以说是一款幻灯片放映插件,它叫Cloud Carousel,支持自动播放.图片预览.鼠标滚轮滚动,非常酷,下图是效果预览. 该jquery图片播放项目演 ...

  8. 理解闭包的微观世界和JS垃圾回收机制

    function a() { ; function b() { alert(++i); } return b; } var c = a(); c(); 一.闭包的微观世界 如果要更加深入的了解闭包以及 ...

  9. shell more less cat

    cat 连续显示.查看文件内容 more 分页查看文件内容 less 分页可控制查看文件内容 通俗点说: cat一次性把文件内容全部显示出来,管你看不看得清,显示完了cat命令就返回了,不能进行交互式 ...

  10. HP Onboard Administrator 固件升级

    HP Onboard Administrator是HP公司服务器的远程管理平台.更新是一个非常简单的过程,可以完全通过办公自动化web管理界面. 1. 下载所需二进制文件 下载地址:HP BladeS ...