如果你还想了解Http的基础知识、通过url获取网络数据以及GET、POST方式上传数据到服务器,请查看我前面几篇博文。Android中的Http通信(一)之Http协议基本知识、Android中的Http通信(二)之根据Url读取网络数据、Android中的Http通信(三)之get、post传递参数到服务器。
本文主要介绍通过多线程的方式从服务器下载数据,这和前两篇博文相比较,增加了线程池以及本地文件读写。如果内心看完前面的几篇博文,这一篇文章,就显得很容易啦。废话不多说,直接开干。
老规矩,先来一个简单的布局,这个布局里面只有一个button和imageview,这里不做任何解释:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/download_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="下载" />
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/download_btn"
android:layout_centerHorizontal="true"
android:background="@drawable/ic_launcher"
android:scaleType="centerCrop" />
</RelativeLayout>
再来看一下Activity中的代码:
package com.example.http;
import java.io.File;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
/**
* 文件下载
*
* @author xiaoyf
*
*/
public class MainActivity extends Activity {
private String fileName;
private ImageView img;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == 1) {
Bitmap bitmap = BitmapFactory.decodeFile(fileName);
img.setImageBitmap(bitmap);
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File parent = Environment.getExternalStorageDirectory();
File file = new File(parent, System.currentTimeMillis() + ".jpg");
fileName = file.getAbsolutePath();
initViews();
}
/**
* 初始化控件
*/
private void initViews() {
img = (ImageView) findViewById(R.id.img);
findViewById(R.id.download_btn).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
new Thread() {
@Override
public void run() {
DownLoadFile downLoadFile = new DownLoadFile(
"http://192.168.197.2:8080/WebProject/girl.jpg",
handler, fileName);
downLoadFile.downLoad();
}
}.start();
}
});
}
}
同样是简单,不做任何解释
![得意](http://static.blog.csdn.net/xheditor/xheditor_emot/default/proud.gif)
![得意](http://static.blog.csdn.net/xheditor/xheditor_emot/default/proud.gif)
![得意](http://static.blog.csdn.net/xheditor/xheditor_emot/default/proud.gif)
下面是核心代码,下载操作都在这里面执行:
package com.example.http;
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;
import android.os.Handler;
/**
* 文件下载
*
* @author xiaoyf
*
*/
public class DownLoadFile {
/**
* 线程池中线程的数量
*/
private static final int THREAD_NUM = 3;
/**
* 连接超时时间、读取超时时间
*/
private static final int TIME_OUT = 5000;
/**
* 完成的线程的数量
*/
private int complete_num;
/**
* 线程池
*/
private Executor executorThread = Executors.newFixedThreadPool(THREAD_NUM);
private String url;
private Handler handler;
private String fileName;
public DownLoadFile() {
super();
}
public DownLoadFile(String url, Handler handler, String fileName) {
super();
this.url = url;
this.handler = handler;
this.fileName = fileName;
}
public void downLoad() {
try {
URL httpUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) httpUrl
.openConnection();
connection.setReadTimeout(TIME_OUT);
connection.setConnectTimeout(TIME_OUT);
connection.setRequestMethod("GET");
connection.setDoInput(true);
long count = connection.getContentLength();
long block = count / THREAD_NUM;
// 计算每个线程下载的起始位置和结束位置;
// 如:待下载的内容有10字节:第一个线程:0-2;第二个线程:3-5;第三个线程:6-10
for (int i = 0; i < THREAD_NUM; i++) {
long start = i * block;
long end = (i + 1) * block - 1;
if (i == THREAD_NUM - 1) {
end = count;
}
DownLoadRunnable runnable = new DownLoadRunnable(start, end);
executorThread.execute(runnable);
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class DownLoadRunnable implements Runnable {
private long start;
private long end;
public DownLoadRunnable() {
}
public DownLoadRunnable(long start, long end) {
this.start = start;
this.end = end;
}
public void run() {
try {
URL httpUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) httpUrl
.openConnection();
connection.setReadTimeout(TIME_OUT);
connection.setConnectTimeout(TIME_OUT);
connection.setRequestMethod("GET");
connection.setDoInput(true);
// 通过http的Range字段,设置从服务器请求数据的开始位置和结束位置
connection.setRequestProperty("Range", "bytes=" + start + "-"
+ end);
// 创建RandomAccessFile对象,"rwd"代表可以对文件进行读写和操作
RandomAccessFile accessFile = new RandomAccessFile(new File(
fileName), "rwd");
// 通过RandomAccessFile对象,设置文件开始写入的位置
accessFile.seek(start);
InputStream in = connection.getInputStream();
//定义一个缓冲数组,大小为2K
byte[] buffer = new byte[1024 * 2];
int len = 0;
while ((len = in.read(buffer)) != -1) {
accessFile.write(buffer, 0, len);
}
if (in != null) {
in.close();
}
if (accessFile != null) {
accessFile.close();
}
complete_num++;
if (complete_num == THREAD_NUM) {
handler.sendEmptyMessage(1);
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
注释的也是相当详细,不做过多解释。文章最后结束的时候,会做一个流程的总结。
OK,我们来看一下运行的效果如何。
看着是不是爽歪歪啊
从美女身上回来,我们最后进行一下流程总结:
1、通过给定的url获得URL以及HttpURLConnection对象,并对HttpURLConnection对象进行基本的设置
2、根据线程池中线程的数量,计算每个线程下载的起始位置和结束位置
3、对线程进行必要的设置,其中包括通过给定的url获得URL以及HttpURLConnection对象,并对HttpURLConnection对象进行基本的设置(特别是通过http的Range字段,设置从服务器请求数据的开始位置和结束位置)、创建RandomAccessFile对象,通过RandomAccessFile对象,设置文件开始写入的位置、
4、启动线程池中各个线程,进行独立下载。
5、记录完成的线程的数量,当完成的线程的数量和线程池中线程的数量相等时,文件下载完毕
项目下载:http://download.csdn.net/detail/u014544193/9415691