您的位置:首页 > 移动开发 > Android开发

android 网络图片异步加载

2015-12-24 16:35 459 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/ws_daydayup/article/details/50395379

原理:

1.通过URL下载网络图片

2.创建异步类AsyncTask执行异步操作

3.将图片写入内存或缓存

4.通知UI更新

重点:

1.使用LruCache缓存Bitmap

2.将图片写入本地下次调用无需下载

3.使用Set集合管理下载任务

4.重写滑动监听实现同步下载


注:详细请看注释



1.图片加载类

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.util.LruCache;
import android.widget.GridView;
import android.widget.ImageView;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

public class LoaderImage {
//图片缓存空间
private LruCache<String, Bitmap> mLruCache;
private GridView mGridView;
//下载任务管理集合
private Set<NewAsyncTask> mTask;

public LoaderImage(GridView gridView) {
mGridView = gridView;
mTask = new HashSet<>();
//为LruCache初始化空间(系统内存的1/8)
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheMemory = maxMemory / 8;
mLruCache = new LruCache<String, Bitmap>(cacheMemory) {
@Override
protected int sizeOf(String key, Bitmap value) {
//每个Bitmap所占内存
return value.getRowBytes() * value.getHeight();
}
};
}

private void addBitmapToLruCache(String path, Bitmap bm) {
if (mLruCache.get(path) == null) {
if (bm != null) {
mLruCache.put(path, bm);
}
}
}

public Bitmap getBitmapByURL(String path) {
Log.d("getBitmapByURL", "--- " + path);
URL myFileURL;
Bitmap bitmap = null;
try {
myFileURL = new URL(path);
HttpURLConnection conn = (HttpURLConnection) myFileURL.openConnection();
conn.setConnectTimeout(6000);
//连接设置获得数据流
conn.setDoInput(true);
//不使用缓存
conn.setUseCaches(false);
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}

//从LruCache中获取图片
public void showImageByAsyncTask(ImageView imageView, String path) {
Bitmap bm = mLruCache.get(path);
if (bm != null) {
imageView.setImageBitmap(bm);
} else {
//自定义未加载完成时的图片
imageView.setImageResource(R.mipmap.ic_launcher);
}
}

//将当前屏幕的图片加入下载任务
public void loadImages(int mStart, int mEnd) {
for (int i = mStart; i < mEnd; i++) {
//ImageYL.Urls[i]
String path = ImageYL.Urls[i];
Bitmap bm = mLruCache.get(path);
if (bm == null) {
NewAsyncTask task = new NewAsyncTask(path);
task.execute(path);
mTask.add(task);
} else {
ImageView imageView = (ImageView) mGridView.findViewWithTag(path);
imageView.setImageBitmap(bm);
}
}
}

//用户滑动时取消下载
public void cancleAllTasks() {
if (mTask != null) {
for (NewAsyncTask task : mTask) {
task.cancel(false);
}
}
}

//图片异步下载类
private class NewAsyncTask extends AsyncTask<String, Void, Bitmap> {
private String mPath;

public NewAsyncTask(String path) {
mPath = path;
}

@Override
protected Bitmap doInBackground(String... params) {
Bitmap bm = null;
//判断SD卡是否存在(下载图片到本地/仅缓存)
if (ExistSDCard()) {
String path = downloadPic(params[0]);
//压缩图片
bm = ImageUtil.decodeSampledBitmapFromPath(path);
} else {
bm = getBitmapByURL(params[0]);
}
if (bm != null) {
addBitmapToLruCache(mPath, bm);
}
return bm;
}

@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
ImageView imageView = (ImageView) mGridView.findViewWithTag(mPath);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
mTask.remove(this);
}
}

//判断有木有SD卡
private boolean ExistSDCard() {
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
return true;
} else
return false;
}

//图片保存到本地
public String downloadPic(String relativePath) {
String filePath = null;
URL picUrl;
HttpURLConnection conn = null;
InputStream fileIn = null;
BufferedOutputStream fileOut = null;
try {
filePath = Environment.getExternalStorageDirectory()
+ File.separator + relativePath;
File picFile = new File(filePath);
if (picFile.exists()) {
return filePath;
}
File dir = new File(picFile.getParent());
if (!dir.isDirectory() || !dir.exists()) {
dir.mkdirs();
}
Log.d("--", "downloadPic,dir:" + dir.getAbsolutePath()
+ ",picFile:" + picFile.getAbsolutePath());
picFile.createNewFile();
picUrl = new URL(relativePath);

conn = (HttpURLConnection) picUrl.openConnection();
fileIn = conn.getInputStream();
fileOut = new BufferedOutputStream(
new FileOutputStream(picFile));
byte[] buf = new byte[1024];
int r = 0, all = 0;
while ((r = fileIn.read(buf)) > 0) {
fileOut.write(buf, 0, r);
all += r;
}

Log.d("--", "read file  : " + relativePath + ",len: " + all);
fileOut.close();
fileIn.close();

} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
} finally {
if (fileIn != null) {
try {
fileIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOut != null) {
try {
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (conn != null) {
conn.disconnect();
}
}
return filePath;
}

}



2.图片压缩类



import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;

public class ImageUtil {

//图片压缩(默认分辨率720*1280)
public static Bitmap decodeSampledBitmapFromPath(String path) {
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeFile(path, options);
options.inSampleSize=caculateInSampleSize(options,720f,1280f);
options.inJustDecodeBounds=false;
Bitmap bm=BitmapFactory.decodeFile(path,options);
return bm;
}
//获取压缩比例
public static int caculateInSampleSize(BitmapFactory.Options options, float reqWidth, float reqHeight) {
int width=options.outWidth;
int height=options.outHeight;
int inSampleSize=1;
if(width>reqWidth||height>reqHeight){
int widthRadio=Math.round(width*1.0f/reqWidth);
int heightRadio=Math.round(height*1.0f/reqHeight);
inSampleSize=Math.max(widthRadio,heightRadio);
}
return inSampleSize;
}
}



3.重写适配器



private class GridViewAdapter extends BaseAdapter implements AbsListView.OnScrollListener {

private int mStart, mEnd;
private boolean mFristin;

public GridViewAdapter(GridView gridView) {
loaderImage = new LoaderImage(gridView);
mFristin = true;
gridView.setOnScrollListener(this);
}

@Override
public int getCount() {
return image_path.size();
}

@Override
public String getItem(int position) {
return image_path.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_grid, null);
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.id_ima);
holder.textView = (TextView) convertView.findViewById(R.id.id_text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String path = image_path.get(position);
holder.imageView.setTag(path);
loaderImage.showImageByAsyncTask(holder.imageView, path);
return convertView;
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//根据用户滑动来决定是否加载图片
if (scrollState == SCROLL_STATE_IDLE) {
loaderImage.loadImages(mStart, mEnd);
} else {
loaderImage.cancleAllTasks();
}
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = firstVisibleItem + visibleItemCount;
//第一次打开加载当前界面图片
if (mFristin && visibleItemCount > 0) {
loaderImage.loadImages(mStart, mEnd);
mFristin = false;
}
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: