这几天实现了一个网络下载图片的功能,并且在ViewPaper和RecyclerView中展示出来。展示出来的功能在我之前写过的一篇文章中。
android 使用RecyclerView实现首项左右滑动,剩余项图片自适应
http://blog.youkuaiyun.com/wb175208/article/details/53618862
以下我主要把下载的过程记录下来:
1.下载的主要使用okhttp框架,异步下载和同步下载都使用了,注意在引用okhttp-3.1.2.jar包时,同时也要使用okio.jar这个包
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import com.test.wb.asynbitmap.listener.IDownLoadCallback;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* Author: aaa
* Date: 2017/1/6 21:14.
* 图片下载管理
*/
public class ImageDownloader {
private static final int IS_SUCCESS = 1;
private static final int IS_FAIL = 0;
//异步获取图片-直接调用
public static void asyncGetImage(String url, final IDownLoadCallback callback) {
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().get()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
byte[] bytes = response.body().bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
callback.sucess(bitmap);
} else {
handler.sendEmptyMessage(IS_FAIL);
}
}
});
}
//同步获取图片 - 需要放在子线程中
public static void synchronizedGetImage(String url, IDownLoadCallback callback) {
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().get()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
byte[] bytes = response.body().bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
callback.sucess(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
private static Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case IS_SUCCESS:
byte[] bytes = (byte[]) msg.obj;
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
// imageView.setImageBitmap(bitmap);
break;
case IS_FAIL:
break;
default:
break;
}
}
};
}
2.RecyclerView在展示图片的时候,采用三级缓存的模式:
a.先检测内存
b.再检测文件
c.最后检测网络下载
private void downloadImage(final ImageView imageView, final String url, final int position) {
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
Bitmap resBitmap = (Bitmap) msg.obj;
imageView.setImageBitmap(resBitmap);
break;
default:
break;
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
//1.先从内存中获取
Bitmap bitmap = getBitmapFromCache(url);
if (bitmap != null) {
Log.i("aaa", "item " + position + " : from Cacher");
// imageView.setImageBitmap(bitmap);
Message message = handler.obtainMessage();
message.what = 0;
message.obj = bitmap;
handler.sendMessage(message);
return;
}
//2.从文件系统中获取
bitmap = ImageLocalManager.getInstance().getBitmapFromFile(url);
if (bitmap != null) {
addBitmapToCache(url, bitmap);
Log.i("aaa", "item " + position + " : from File");
Message message = handler.obtainMessage();
message.what = 0;
message.obj = bitmap;
handler.sendMessage(message);
// imageView.setImageBitmap(bitmap);
return;
}
//3.从网上下载
ImageDownloader.asyncGetImage(url, new IDownLoadCallback() {
@Override
public void sucess(final Bitmap bitmap) {
Log.i("aaa", "item " + position + " : from DownLoader");
addBitmapToCache(url, bitmap);
ImageLocalManager.getInstance().saveImageToFile(url, bitmap);
Message message = handler.obtainMessage();
message.what = 0;
message.obj = bitmap;
handler.sendMessage(message);
}
@Override
public void failed(Bitmap bitmap) {
}
});
}
}).start();
}
3.ViewPaper展示图片的方式,也是通过同步下载的方式下载图片,顺便总结一下ViewPaper。使用ViewPaper时,要使用PagerAdapter作为适配器,ViewPager初始化的时候首先调用:
public Object instantiateItem(ViewGroup container, int position)
初始化第0页和第1页。而且ViewPager初始化页面的始终是保持中间和左右三个页面存在,如果是第一次初始化,只保存前两张页面;当滑动到最后一页的时候,只保存最后两张页面。其余的页面会通过以下函数移除掉:
public void destroyItem(ViewGroup container, int position, Object object)
然后在展示图片的时候,重写以上两个方法就可以了
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// 当前位置的View移除
container.removeView(mImageViews.get(position).mImageView);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mImageViews.get(position).mImageView);
// return mImageViews.get(position);
return getView(mImageViews.get(position), position);
}
private ImageView getView(final ViewPagerData data, final int position) {
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
Log.i("aaa", "page " + position + " : form Download");
Bitmap bitmap = (Bitmap) msg.obj;
data.mImageView.setImageBitmap(bitmap);
break;
}
}
};
data.mImageView.setImageBitmap(mDefaultBitmap);//设置默认图片
Bitmap bitmap = mViewPaperCache.get(data.mUrl);
if (bitmap != null) {
Log.i("aaa", "page " + position + " : form cache");
data.mImageView.setImageBitmap(bitmap);
return data.mImageView;
}
bitmap = ImageLocalManager.getInstance().getBitmapFromFile(data.mUrl);
if (bitmap != null) {
mViewPaperCache.put(data.mUrl, bitmap);
Log.i("aaa", "page " + position + " : form file");
data.mImageView.setImageBitmap(bitmap);
return data.mImageView;
}
new Thread(new Runnable() {
@Override
public void run() {
ImageDownloader.synchronizedGetImage(data.mUrl, new IDownLoadCallback() {
@Override
public void sucess(Bitmap bitmap) {
mViewPaperCache.put(data.mUrl, bitmap);
ImageLocalManager.getInstance().saveImageToFile(data.mUrl, bitmap);
Message message = Message.obtain();
message.what = 0;
message.obj = bitmap;
handler.sendMessage(message);
}
@Override
public void failed(Bitmap bitmap) {
}
});
}
}).start();
return data.mImageView;
}
4.缓存成文件的图片,保存到本地磁盘中,通过MD5的方式命名,防止出现图片名字重复
5.在Android6.0以上使用的时候,主要要动态加载权限