概述
在某些开发场景可能涉及到图片下载,由于现在手机分辨率普遍较高,所以为了保证高质量的显示效果,所以图片的分辨率也一样较高,这样的直接后果就是,图片内存大,所以下载的时候会花费较多的时间和流量。同样的,为了提高下载图片的性能,我们很直接的想到了用多线程去下载图片,今天 我们要讲的就是如何用多线程下载图片。
今天会用到以下知识,线程池,RandomAccessFile 类等。
我们先来履一下我们的思路
- 首先获取文件的实际字节长度,然后将文件分块
- 对分块后的文件,用不同的子线程去下载,写进 RandomAccessFile 中
具体的实现代码
主 Activity 代码
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.example.yimeng.emptyapplication.R;
import util.HttpUtil;
/**
* Created by yimeng on 2015-08-27.
*/
public class DownLoadActivity extends Activity{
private Button button;
private ImageView imgv;
private String url = "http://img5.duitang.com/uploads/item/201408/12/20140812133247_zcLCB.jpeg";
private final int IS_OK =1;
private Bitmap bitmap =null;
private Drawable drawable;
private Handler handler =new Handler() {
private int count =0;
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case IS_OK:
count++;
if(count == 3){
Toast.makeText(getApplicationContext(),"receive",Toast.LENGTH_SHORT).show();
imgv.setImageDrawable(drawable);
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
init();
}
private void init() {
button = (Button) findViewById(R.id.but_download);
imgv = (ImageView) findViewById(R.id.imgv_download);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
drawable = getApplicationContext().getResources().getDrawable(R.drawable.assint);
new Thread(new Runnable() {
@Override
public void run() {
HttpUtil.downLoad(url,handler);
}
}).start();
}
});
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/imgv_download"
/>
<Button
android:id="@+id/but_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="download"
android:textSize="18sp"
android:background="#f62"
android:layout_marginTop="20dp"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
tip:这里用的的 drawable 只是一张图片,这里就不上传了,读者只需要将这一行代码中的 R.drawable.assint 换成自己drawable 文件夹中的文件 ID就可以了
drawable = getApplicationContext().getResources().getDrawable(R.drawable.assint);
工具类:
import android.graphics.Bitmap;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
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.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by yimeng on 2015-08-27.
*/
public class HttpUtil {
public static void downLoad(String mUrl,Handler handler) {
HttpURLConnection connection =null;
URL url =null;
ExecutorService executorService = Executors.newFixedThreadPool(3);
try {
url = new URL(mUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setDoOutput(true);
connection.setDoInput(true);
long totalLength = connection.getContentLength();
long block = totalLength/3;
File parent = Environment.getExternalStorageDirectory();
String filePath =parent.getAbsolutePath()+File.separator+"aa.jpg";
Log.v("filePath",filePath);
// RandomAccessFile childFile = new RandomAccessFile(new File(filePath),"rwd");
// 为线程池开启三个子线程
for(int i = 0;i<3;i++){
long start = block*i;
long end = block*(i+1)-1;
if(i == 2){
end = totalLength;
}
DownLoadRunnable runnable = new DownLoadRunnable(start,end,mUrl,handler,filePath);
executorService.execute(runnable);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getFileName(String url){
return url.substring(url.lastIndexOf("/"+1));
}
public static class DownLoadRunnable implements Runnable {
private long start; // 开始字段
private long end; // 结束字段
private String url; // 下载地址
private Handler handler;
private String fileName;
public DownLoadRunnable(long start, long end, String url,Handler handler,String filename) {
this.start = start;
this.end = end;
this.url = url;
this.handler = handler;
this.fileName = filename;
}
@Override
public void run() {
HttpURLConnection connection = null;
URL purl = null;
try {
purl = new URL(url);
connection = (HttpURLConnection) purl.openConnection();
connection.setConnectTimeout(5000);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("GET");
connection.setRequestProperty("Range","bytes="+start+"-"+end);
int len = 0;
RandomAccessFile file = new RandomAccessFile(new File(fileName),"rwd");
file.seek(start);
byte [] buffer =new byte[4*1024];
InputStream is = connection.getInputStream();
while ((len=is.read(buffer))!=-1){
file.write(buffer,0,len);
}
if(is!=null){
is.close();
}
if(file!= null){
file.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Message msg = Message.obtain();
msg.what = 1;
handler.sendMessage(msg);
}
}
}
实现效果图,未下载
下载成功
查看结果