Android之单线程下载与多线程下载
2015-09-14 19:34
1046 查看
概述:
单线程下载很简单,就是开启一个线程去下载资源再进行本地保存;多线程下载是通过RandomAccessFile(随机文件读写操作类)来设置每个线程读取文件的起始点位置,起始点之间的长度即为该线程需要下载的文件大小
下载开始位置:线程id*每条线程下载的数据长度 = ?
下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?
这里用的是URLConnection
单线程下载与多线程下载
public class DownloadActivity extends Activity implements View.OnClickListener { private Button mButtonSingle; private Button mButtonMuti; private SeekBar mSeekBarDownload; private int fileLength; //handler用于接收多线程下载线程的消息Message,并得到文件下载进度写入进度条SeekBar private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case 0x23: mSeekBarDownload.setProgress(msg.arg1*100/fileLength); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download); mSeekBarDownload = (SeekBar) findViewById(R.id.seekBar_download); mButtonSingle = (Button) findViewById(R.id.button_download_single); mButtonMuti = (Button) findViewById(R.id.button_download_muti); mButtonSingle.setOnClickListener(this); mButtonMuti.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.button_download_single: new SingleDownloadTask().execute(); break; case R.id.button_download_muti: new Thread(new Runnable() { @Override public void run() { downloadMuti(); } }).start(); break; default: break; } } /** * 多线程下载方式 * 作用是打开网络连接,建立被下载文件存放路径,开启多个下载线程并发送文件下载进度的消息 */ private void downloadMuti() { try { String urlPath = "http://192.168.0.30:8080/MyWebTest/music/aa.mp3"; URL url = new URL(urlPath); //连接下载地址 URLConnection connection = url.openConnection(); //得到文件长度 fileLength = connection.getContentLength(); //找到或创建下载文件的存放路径 File file = new File(Environment.getExternalStorageDirectory(),"ee.mp3"); if(!file.exists()){ file.createNewFile(); } MutiThread[] threads = new MutiThread[5]; //进行五次分段下载,因为int型的整除会舍弃余数,最后一个进程下载的长度是从文件长度的4/5到文件总长度 for(int i=0;i<5;i++){ MutiThread thread = null; if(i==4){ thread = new MutiThread(fileLength/5*4,fileLength,urlPath,file.getAbsolutePath()); }else{ thread = new MutiThread(fileLength/5*i,fileLength/5*(i+1)-1,urlPath,file.getAbsolutePath()); } thread.start(); threads[i] = thread; } boolean isFinish = true; //如果没有下载完全时不断的更新下载进度,数据通过Message传递给handler while (isFinish){ int sum=0; for(MutiThread thread:threads){ sum+=thread.getSum(); } Message msg = handler.obtainMessage(); msg.what = 0x23; msg.arg1 = sum; handler.sendMessage(msg); //一般一个被下载的文件可能无法下载完全 if(sum+10>fileLength){ isFinish=false; } //被隔一秒,更新一次进度 Thread.sleep(1000); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } //单线程下载,用的是AsyncTask线程 class SingleDownloadTask extends AsyncTask<String,Integer,String>{ @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); mSeekBarDownload.setProgress((int) (values[0]*100.0/values[1])); } @Override protected void onPostExecute(String s) { super.onPostExecute(s); } @Override protected String doInBackground(String... params) { try { URL url = new URL("http://192.168.0.30:8080/MyWebTest/music/aa.mp3"); URLConnection connection = url.openConnection(); int length = connection.getContentLength(); InputStream is = connection.getInputStream(); File file = new File(Environment.getExternalStorageDirectory(),"aa.mp3"); if(!file.exists()){ file.createNewFile(); } FileOutputStream fos = new FileOutputStream(file); byte[] array = new byte[1024]; int index = is.read(array); int progress = 0; while(index!=-1){ fos.write(array,0,index); progress+=index; publishProgress(progress,length); index = is.read(array); } fos.flush(); fos.close(); is.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } } }
多线程的下载线程的写法
public class MutiThread extends Thread { private int sum = 0; private long start; private long end; private String urlPath; private String filePath; public MutiThread(long start, long end, String urlPath, String filePath) { this.start = start; this.end = end; this.urlPath = urlPath; this.filePath = filePath; } public int getSum() { return sum; } @Override public void run() { try { URL url = new URL(urlPath); URLConnection connection = url.openConnection(); connection.setAllowUserInteraction(true); //设置当前线程下载的起点,终点 connection.setRequestProperty("Range", "bytes=" + start + "-" + end); InputStream is = connection.getInputStream(); byte[] array = new byte[1024]; File file = new File(filePath); //使用java中的RandomAccessFile 对文件进行随机读写操作 RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw"); //设置开始写文件的位置 randomAccessFile.seek(start); int index = is.read(array); //开始循环以流的形式读写文件 while(index!=-1){ randomAccessFile.write(array,0,index); sum += index; index = is.read(array); } randomAccessFile.close(); is.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
结果演示:
单线程下载:
多线程下载:
显然,多线程下载要比单线程下载快得多,但前提是手机是多核的。
相关文章推荐
- 如何检查 Android 应用的内存使用情况
- 使用Android Studio的硬件配置
- 关于Android中,保留小数点后两位的方式
- android如何通过TextView实现不同的Activity的切换
- android的json解析
- Android(java)学习笔记248:ContentProvider使用之虚拟短信
- android学习之路之通知-Notification
- android .9.png ”点九” 图片制作方法
- 怎样根据下载链接得到文件名(并非直接从链接中截取)
- Android 搜索附近wifi并连接
- 关于android support v7包的使用
- TransitionDrawable一个能渐变显示的Drawable
- 9.14学习笔记 studiojar包生成,android插件,毛玻璃
- Android开发环境搭建
- Android , 浅谈显示Intent和隐式Intent
- Android硬件抽象层(HAL)概要介绍和学习计划
- Android反调试之 AntiEmulator 检测安卓模拟器
- Android设置默认Launcher
- Android 实时视频采集—MediaRecoder录制
- 关于Android开发中Activity的启动模式