安卓基础:实现多线程下载本次服务器的图片
2016-03-16 14:25
204 查看
实现原理
(1)首先获得下载文件的长度,然后设置本地文件的长度。
(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。
如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示:
(网上找的图)
例如10M大小,使用3个线程来下载,
线程下载的数据长度 (10%3 == 0 ? 10/3:10/3+1) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M
下载开始位置:线程id*每条线程下载的数据长度 = ?
下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?
直接上代码:
1.DownLoad.java
2.MainActivity.java
3.布局文件就一个按钮和一个TextView,下面是结果图
(1)首先获得下载文件的长度,然后设置本地文件的长度。
(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。
如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示:
(网上找的图)
例如10M大小,使用3个线程来下载,
线程下载的数据长度 (10%3 == 0 ? 10/3:10/3+1) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M
下载开始位置:线程id*每条线程下载的数据长度 = ?
下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?
直接上代码:
1.DownLoad.java
import android.os.Environment; import android.os.Handler; import android.os.Message; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class DownLoad { private Handler handler; public DownLoad(Handler handler) { this.handler = handler; } //创建是哪个线程池,用来下载数据 private Executor threadPool = Executors.newFixedThreadPool(3); //给线程池创建一个Runnable对象 static class DownLoadRunnable implements Runnable{ private String url; private String fileName; private long start;//下载的启示位置 private long end;//下载的结束位置 private Handler handler; public DownLoadRunnable(String url, String fileName, long start, long end, Handler handler) { this.url = url; this.fileName = fileName; this.start = start; this.end = end; this.handler = handler; } @Override public void run() { try { URL httpUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); /* 1.Http协议字段 Range "bytes="+start+"-"+end 2.RandomAccessFile设置写入的位置 3.开启线程发送网路请求 */ conn.setRequestProperty("Range", "bytes=" + start + "-" + end);//获得请求数据的长度; //通过RandomAccessFile(随机读取流)对本地文件进行写操作,rwd代表可读可写可执行 RandomAccessFile access = new RandomAccessFile(new File(fileName),"rwd"); access.seek(start);//从start开始写 InputStream in = conn.getInputStream(); byte[] b = new byte[1024*4];//创建一个缓冲区,4K int len = 0; while((len = in.read(b))!=-1){ access.write(b,0,len);//从0开始,读取len的一个长度 } //读取完之后关闭这个流 if(access!=null){ access.close(); } //读取玩之后关闭输入流 if(in!=null){ in.close(); } //所有文件下载完成之后,给主线程发送一个消息 Message message = new Message(); message.what = 1; handler.sendMessage(message); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /** * 多线程文件下载 */ public void downLoadFile(String url){ try { URL httpUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); //拿到用来下载图片的长度 int count = conn.getContentLength(); //将长度分为三段 int block = count/3; //指定一个文件的名字 String fileName = getFileName(url); //拿到文件名后,需要指定一个文件的下载地址,下载到SD卡 File parent = Environment.getExternalStorageDirectory(); File fileDownLoad = new File(parent,fileName); //往线程池提交任务 /** * 假如有11个字节,则11/3 = 3 * 第一个线程 0-2 * 第二个线程 3-5 * 第三个线程 6-10 最后一个线程处理多出来的 */ for (int i = 0; i<3;i++){ long start = i*block; long end = (i+1)*block-1; if(i==2){ end = count; } //fileDownLoad.getAbsolutePath()是获取绝对路径 DownLoadRunnable runnable = new DownLoadRunnable(url, fileDownLoad.getAbsolutePath(),start,end,handler); //通过线程池去提交任务 threadPool.execute(runnable); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //取出url后缀名的方法 public String getFileName(String url){ return url.substring(url.lastIndexOf("/")+1); } }
2.MainActivity.java
package com.ceshi.hwy.download; import android.app.Activity; import android.os.Handler; import android.os.Message; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private Button button; private TextView textView; private int count = 0; /** * 使用Handler更新UI界面信息 */ private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { int result = msg.what; count+=result; if(count == 3){ textView.setText("download success!!!"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); textView = (TextView) findViewById(R.id.textview); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(){ @Override public void run() { DownLoad downLoad = new DownLoad(handler); downLoad.downLoadFile("http://192.168.173.1:8080/web/hai.jpg"); } }.start(); } }); } }
3.布局文件就一个按钮和一个TextView,下面是结果图
相关文章推荐
- CUBRID学习笔记 7 ms常见错误
- zepto.js
- 重新启动IIS不重启电脑
- [JAVA关键字] synchronized
- mediaplayer与surfaceView,无法播放问题
- Spring对AOP的支持
- Android Fragment完全解析,关于碎片你所需知道的一切
- LeetCode Populating Next Right Pointers in Each Node II
- 供应用程序调用的中断 (7CH - 平方运算)
- 经验总结一
- 作业二(2)流行的源程序版本管理软件和项目管理软件各自的优点缺点
- 一个IP建多个Web站点
- 使用Gradle发布aar项目到JCenter仓库
- Logback的配置文件查找顺序
- Maximum GCD + ungetc()函数的使用
- Spring 定时任务执行两次 解决办法
- React组件详细介绍及其生命周期函数
- 每句话的含义你懂吗?
- String.format()用法
- 2015年 微电子科学与工程专业 大学排名