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-sdkandroid: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"/><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid: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;//当前值@Overrideprotected 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 blocke.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() {@Overridepublic 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() {@Overridepublic void run() {// TODO Auto-generated method stubToast.makeText(MainActivity.this, "SD卡不存在", 1).show();}});}} else {runOnUiThread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubToast.makeText(MainActivity.this, "server端返回错误", 1).show();}});}} catch (Exception e) {// TODO Auto-generated catch blocke.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;}@Overridepublic 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对象openConnectionHttpURLConnection 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"头,返回的状态码就是206if (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() {@Overridepublic 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() {@Overridepublic void run() {// TODO Auto-generated method stubToast.makeText(MainActivity.this, "当前线程" + threadId + "---完成下载", 1).show();}});/*** 第五步:当你的n个线程都完成下载 的时候我才进行删除记录下载位置的缓存文件*/deleteRecordFile();} else {runOnUiThread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubToast.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() {@Overridepublic void run() {tv_pb.setText("当前的进度是:"+currentPb*100/pb_download.getMax()+"%");}});

执行结果

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

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

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

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

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

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

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

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

赵雅智_android多线程下载带进度条相关推荐

  1. C# 下载带进度条代码(普通进度条)

    <span style="font-size:14px;"> </span><pre name="code" class=&quo ...

  2. Android FTP 客户端 上传/下载 带进度条实战源码

    Android FTP 开发,我个人是使用commons-net-3.1.jar,别问我为什么是度娘教我的,附上commons-net-3.1.jar的开源下载地址http://grepcode.co ...

  3. 赵雅智:android教学大纲

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

  4. 从FTP下载文件带进度条

    1 #region 获取FTP服务器上指定文件的大小 2 /// <summary> 3 /// 获取FTP服务器上指定文件的大小 4 /// </summary> 5 /// ...

  5. 带进度条的ASP无组件断点续传下载代码

    <%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%> <%Option Explicit%> <% '= ...

  6. 微信小程序下载视频到相册(带进度条)

    微信小程序下载视频到相册,并带进度条 <button class="desc-note my-button u-font-32" @click="toUpload( ...

  7. C#winform 从ftp下载文件(带进度条)、获取文件(夹)的名字

    直接用地址下载,引用进度条: ​/// <summary>/// 从ftp服务器下载文件的功能----带进度条/// </summary>/// <param name= ...

  8. python ftp上传/下载文件,带进度条显示

    文章目录 想法 最终效果 python代码 补充:下载带进度显示 想法 用python写个ftp上传文件的功能,想要实时看到上传进度,进度条ui部分,使用python的tkinter库实现. 最终效果 ...

  9. 图片轮播php代码下载,jQuery带进度条滚动图片轮播代码

    jQuery带进度条滚动图片轮播代码 jQuery带进度条滚动图片轮播代码是一款带左右箭头按钮控制图片滚动轮播,标题和进度条显示效果. $(document).ready(function(e) { ...

最新文章

  1. SpringMVC——通俗易懂讲讲Ajax~
  2. 优秀学生专栏——孙珩发
  3. 现在股市里人人都在赚钱!!到底谁在亏钱?我讲一个故事来告诉大家谁亏钱了...
  4. [Java] 蓝桥杯ADV-209 算法提高 c++_ch02_04
  5. 登录emc磁阵提示java版本低_安装完打开 eclipse 提示 JVM 版本较低
  6. 笔记 GWAS 操作流程2-1:缺失质控
  7. 指数函数曲线拟合问题c语言,求助用指数函数拟合一组数据
  8. 使用行列式公式求多边形面积
  9. QCMS企业建站系统 v5.0.1
  10. java34-计算机的发展-计算机硬件-计算机软件-计算机存储规则-计算机的基本操作-CMD-环境变量
  11. java+url+空格转码_Web里URL空格的转换方法
  12. XML编程经验――LIBXML2库使用指南
  13. CSP 2017-12
  14. 珞珈-B生所学 跟学笔记 PPT(三)(完结)
  15. HCIA 交换机原理与ARP协议
  16. 四篇文章带你快速入门Jetpck(中)之ViewModel,DataBinding
  17. expire_logs_days
  18. linux 进城 io字节,(2)linux内核之内存分配与IO口操作
  19. 偏微分方程的物理含义
  20. 低代码助力企业快速搭建进销存

热门文章

  1. 【Java】eclipse如何导入项目
  2. Unity Remote使用方法
  3. vmware虚拟机ubuntu开机黑屏问题解决
  4. c语言函数参数类型检查,内联函数在编译时是否做参数类型检查?
  5. java 工厂 单例_java 单例模式和工厂模式实例详解
  6. 拿到input输入的时间_【Keras 笔记】Input/Dense层的数学本质
  7. java读avro的流_0016-Avro序列化反序列化和Spark读取Avro数据
  8. SpringBoot获取请求的参数
  9. Docker运行PostgreSQL
  10. non-member function cannot have cv-qualifier