Android 单线程下载与多线程下载
2015-09-12 22:27
531 查看
一、搭建severlet服务器
上面的图片展示的只是我们在搭建好服务器的情况下,新建一个Serverlet的方式。具体的从头开始搭建Serverlet的方式大家可以查看下面的连接。
Serverlet具体的搭建方法
注:如果之前已经搭建好的服务器,但是现在不能用了,出现404 错误的,可以参考以上代码重新搭建一遍就能用了。
二、单线程下载
单线程的下载思想就是通过URL来连接Web的下载路径,这样我们一边读入再写出到手机上就可以了。由于主线程中不能操作UI界面、不能有耗时操作,这里我们通过之前的异步加载AsyncTask(封装好的Thread)来实现。
注:异步加载AsyncTask中不能使用Toast语句,可以使用Log来代替。
思路
1、新建一个类继承AsyncTask,在它的doInBackground方法中进行URL连接、读入与写出2、对Button点击事件监听,当有点击时开启该线程即可。
[code] class SingleDownload extends AsyncTask<String, Integer, String> { @Override protected String doInBackground(String... params) { try { //获得URL路径 URL url = new URL( "http://192.168.0.35:8080/Myserverlets/music/aa.mp3"); //获得URL连接 URLConnection connection = url.openConnection(); //获得文件的总长度 int length = connection.getContentLength(); //获得输入流 InputStream is = connection.getInputStream(); //新建要写入的文件 File file = new File(Environment.getExternalStorageDirectory(), "bb.mp3"); if (!file.exists()) { file.createNewFile(); } //获得输出流 FileOutputStream os = new FileOutputStream(file); //通过字节读取,每次读取1024B byte[] array = new byte[1024]; int sum = 0; int index = is.read(array); while (index != -1) { //写出array,长度0~index os.write(array, 0, index); sum += index; publishProgress(sum, length); index = is.read(array); } os.flush(); os.close(); is.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); Toast.makeText(getApplicationContext(), "执行" + values[0], Toast.LENGTH_SHORT).show(); progressbar.setProgress((int) (values[0] * 100.0 / values[1])); Toast.makeText(getApplicationContext(), "执行" + values[1], Toast.LENGTH_SHORT).show(); } @Override protected void onPostExecute(String result) { super.onPostExecute(result); } } }
Button监听
[code]case R.id.download_single: SingleDownload singledownload = new SingleDownload(); singledownload.execute(); break;
三、多线程下载
多线程下载的思想是开启多个线程将一整个文件进行分段现在,下载开始的位置不同,比如我们的一个文件大小为11,假设我们想要开启3个线程,这样我们第一线程的写出位置为0~2,第二个线程的写出位置为3~5,第三个线程的写出位置本来应该是6~8这样我们还剩了一小部分没有写出,因此我们将第三个线程的写出的结束位置修改为10 ,这样就可以全部写出了。同样因为网络下载是一种耗时操作,我们需要新启线程,并在线程中新启多个线程同时下载。当按钮点击时调用下面方法。
步骤:
1、先写要开启的多个线程
2、再在MainActivity中开启线程来开启多线程(这里我们用了一个Thread数组对多线程进行管理,其实也可以使用线程池来管理Executor来管理)
代码示例
1、开启的多个线程[code]public class MultiDownLoad extends Thread { private String urlpath; private String filepath; private long start; private long end; private long length; private long sum=0; public MultiDownLoad(String url, String filepath, long start, long end) { this.urlpath = url; this.filepath = filepath; this.start = start; this.end = end; } public long getSum() { return sum; } @Override public void run() { try { URL url=new URL(urlpath); URLConnection conn=url.openConnection(); conn.setAllowUserInteraction(true); conn.setRequestProperty("Range", "bytes="+start+"-"+end); InputStream is=conn.getInputStream(); byte[] array=new byte[1024]; File file=new File(filepath); 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(); } if(randomAccessFile!=null){ randomAccessFile.close(); } if(is!=null){ is.close(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
2、在MainActivity中开启线程来开启多线程,按钮点击时调用该方法。
[code]private void mutidownload() { new Thread(){ @Override public void run() { String urlpath="http://192.168.0.35:8080/Myserverlets/music/aa.mp3"; try { URL url=new URL(urlpath); URLConnection conn=url.openConnection(); length=conn.getContentLength(); // String fileName=getFileName(urlpath); Log.d("文件名",fileName); File file=new File(Environment.getExternalStorageDirectory(),fileName); if(!file.exists()){ file.createNewFile(); } MultiDownLoad[] multithread=new MultiDownLoad[4]; for(int i=0;i<4;i++){ MultiDownLoad thread=null; long start=length/4*i; long end=length/4*(i+1); if(i==3){ end=length; } thread=new MultiDownLoad(urlpath,file.getAbsolutePath(), start, end); thread.start(); multithread[i]=thread; } boolean isfinish=true; while(isfinish){ long sum=0; for(MultiDownLoad thread:multithread){ sum+=thread.getSum(); } Message msg=handler.obtainMessage(); msg.obj=sum; msg.what=0x233; handler.sendMessage(msg); if(sum+10>=length){ isfinish=false; } Thread.sleep(1000); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } //该方法用于获得要保存成的文件名 private String getFileName(String url){ return url.substring(url.lastIndexOf("/")+1); }
学习注意点:
1、单线程与AsycTask的结合使用2、多线程的思路(线程中再开多个线程)
3、获得要保存成的文件名的方式
相关文章推荐
- Android:LayoutInflater介绍
- Android屏幕适配
- 2. Android系统结构
- Android0909<十四>(Service、Android线程)
- Android中AIDL使用例子
- Android 动画深入分析
- 如何在Android模拟器上安装apk文件
- android获取asset文件存到SD卡
- Glide图片加载器详解(PPT转录)
- android---AlertDialog对话框解析
- Android Studio中使用*.jar,*.aar和*.so文件
- Android开发环境的发展演变
- javaS的tring和androidS的tring区别是什么?
- Android开发之路(二)--浅析MVC开发模式
- 超轻量级的安卓SlidingMenu库
- Android JNI的动态注册
- Android 使用ShardSDK实现社会化分享
- Android(java)学习笔记237:多媒体之图形的变化处理
- leakcanary作者发现的一个Dialog的各种listener容易引发的内存泄露问题
- Android开发-Activity(一)