一、首先,废话不多说,先上图片
二、实现思路
1、缓存在本地和内存中,每次加载都从本地中读取,如果本地没有则从网络下载,并保存到本地或者内存
2、内存缓存使用软引用和LruCache算法
3、本地缓存使用DiskLruCache算法
4、LruCache算法系统自带,DiskLruCache算法如果没有可以去网上下载,当然最后我会在我的资源里放上源码
三、实现
1、创建文件目录
2、先创建图片缓存接口 BitmapCache且实现该接口
public interface BitmapCache {
/**
* 缓存bitmap
* @param request
* @param bitmap
*/
void put(BitmapRequest request, Bitmap bitmap);
/**
* 通过请求去bitmap
* @param request
* @return
*/
Bitmap get(BitmapRequest request);
/**
* 移除bitmap
* @param request
*/
void remove(BitmapRequest request);
}
本地缓存实现 DiskCache.java
public class DiskCache implements BitmapCache {
private static DiskCache mDiskCache;
//缓存路径 ,这里可以换成你想要保存的名字和路径
private String mCacheDir = "testImage";
//MB
private static final int MB = 1024 * 1024;
private DiskLruCache mDiskLruCache;
public DiskCache(Context context) {
initDiskCache(context);
}
public static DiskCache getInstance(Context context) {
if (mDiskCache == null) {
synchronized (DiskCache.class) {
if (mDiskCache == null) {
mDiskCache = new DiskCache(context);
}
}
}
return mDiskCache;
}
private void initDiskCache(Context context) {
//得到缓存的目录 data/data目录下,好处,app卸载后,文件自动被删除
File directory = getDiskCacheDir(mCacheDir, context);
if (!directory.exists()) {
directory.mkdirs();
}
try {
//mxSize 指定缓存容量
mDiskLruCache = DiskLruCache.open(directory, 1, 1, 50 * MB);
} catch (IOException e) {
e.printStackTrace();
}
}
private File getDiskCacheDir(String mCacheDir, Context context) {
File cacheDir = context.getCacheDir();
File newCacheDir = new File(cacheDir, mCacheDir);
Log.i("wxf", "new cache path:" + newCacheDir.getAbsolutePath());
return newCacheDir;
}
@Override
public void put(BitmapRequest request, Bitmap bitmap) {
DiskLruCache.Editor editor = null;
OutputStream os = null;
try {
//路径必须是合法字符
editor = mDiskLruCache.edit(request.getImageUriMD5());
os = editor.newOutputStream(0);
if (os != null) {
if (persistBitmap2Disk(bitmap, os)) {
editor.commit();
} else {
editor.abort();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean persistBitmap2Disk(Bitmap bitmap, OutputStream os) {
//图片质量压缩
BufferedOutputStream bos = new BufferedOutputStream(os);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
try {
bos.flush();
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
IOUtil.closeQuietly(bos);
}
return true;
}
@Override
public Bitmap get(BitmapRequest request) {
try {
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(request.getImageUriMD5());
if (snapshot != null) {
InputStream inputStream = snapshot.getInputStream(0);
return BitmapFactory.decodeStream(inputStream);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public void remove(BitmapRequest request) {
try {
mDiskLruCache.remove(request.getImageUriMD5());
} catch (IOException e) {
e.printStackTrace();
}
}
}
内存缓存实现 MemoryCache.java
public class MemoryCache implements BitmapCache {
private LruCache<String, Bitmap> mLruCache;
public MemoryCache() {
int maxSize = (int) (Runtime.getRuntime().freeMemory() / 1024 / 8);
mLruCache = new LruCache<String, Bitmap>(maxSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
};
}
@Override
public void put(BitmapRequest request, Bitmap bitmap) {
mLruCache.put(request.getImageUriMD5(), bitmap);
}
@Override
public Bitmap get(BitmapRequest request) {
return mLruCache.get(request.getImageUriMD5());
}
@Override
public void remove(BitmapRequest request) {
mLruCache.remove(request.getImageUriMD5());
}
}
缓存调用 DoubleCache.java
public class DoubleCache implements BitmapCache {
//内存缓存
private MemoryCache mMemoryCache = new MemoryCache();
// 硬盘缓存
private DiskCache mDiskCache;
public DoubleCache(Context context) {
mDiskCache = DiskCache.getInstance(context);
}
@Override
public void put(BitmapRequest request, Bitmap bitmap) {
mMemoryCache.put(request, bitmap);
mDiskCache.put(request, bitmap);
}
@Override
public Bitmap get(BitmapRequest request) {
Bitmap bitmap = mMemoryCache.get(request);
if (bitmap == null) {
bitmap = mDiskCache.get(request);
if (bitmap != null) {
//放入内存,方便获取
mMemoryCache.put(request, bitmap);
}
}
return bitmap;
}
@Override
public void remove(BitmapRequest request) {
mMemoryCache.remove(request);
mDiskCache.remove(request);
}
}
3、设置加载中和加载失败的默认图片 Displayconfig.java
public class Displayconfig {
/**
* 加载过程中默认显示的图片Id
*/
public int loadingImage = -1;
/**
* 加载失败显示的图片
*/
public int failImage = -1;
}
4、图片加载配置 ImageLoaderConfig.java
public class ImageLoaderConfig {
//缓存策略
private BitmapCache bitmapCache=new MemoryCache();
//加载策略
private LoadPolicy loadPolicy=new ReversePolicy();
//默认加载线程数
private int threadcount = Runtime.getRuntime().availableProcessors();
//显示配置
private Displayconfig displayconfig=new Displayconfig();
private ImageLoaderConfig() {
}
/**
* 建造者模式
*/
public static class Builder {
private ImageLoaderConfig config;
public Builder() {
this.config = new ImageLoaderConfig();
}
/**
* 设置缓存策略
*
* @param bitmapCache
* @return
*/
public Builder setCachePlicy(BitmapCache bitmapCache) {
this.config.bitmapCache = bitmapCache;
return this;
}
/**
* 设置加载策略
*
* @param loadpolicy
* @return
*/
public Builder setLoadpolicy(LoadPolicy loadpolicy) {
this.config.loadPolicy = loadpolicy;
return this;
}
/**
* 设置线程数量
*
* @param threadCount
* @return
*/
public Builder setThreadCount(int threadCount) {
this.config.threadcount = threadCount;
return this;
}
/***
* 设置加载过程中的图片
* @param ResID
* @return
*/
public Builder setLoadingImage(int ResID) {
this.config.displayconfig.loadingImage = ResID;
return this;
}
/**
* 设置加载失败的图片
*
* @param ResID
* @return
*/
public Builder setFailImage(int ResID) {
this.config.displayconfig.failImage = ResID;
return this;
}
public ImageLoaderConfig build(){
return this.config;
}
}
public BitmapCache getBitmapCache() {
return bitmapCache;
}
public LoadPolicy getLoadPolicy() {
return loadPolicy;
}
public int getThreadcount() {
return threadcount;
}
public Displayconfig getDisplayconfig() {
return displayconfig;
}
}
5、创建加载接口 Loader.java
public interface Loader {
/**
* 加载图片
*
* @param request
*/
void loadImage(BitmapRequest request);
}
实现图片的加载类以实现控制图片加载 SimpleImageLoader.java
public class SimpleImageLoader {
/**
* 配置文件
*/
private ImageLoaderConfig config;
/**
* 请求队列
*/
private RequestQueue mRequestQueue;
/**
* 单例对象
*/
private static volatile SimpleImageLoader mInstance;
private SimpleImageLoader() {
}
private SimpleImageLoader(ImageLoaderConfig imageLoaderConfig) {
this.config = imageLoaderConfig;
mRequestQueue = new RequestQueue(config.getThreadcount());
//开启队列
mRequestQueue.start();
}
/**
* 获取单例方法
*
* @param config
* @return
*/
public static SimpleImageLoader getInstance(ImageLoaderConfig config) {
if (mInstance == null) {
synchronized (SimpleImageLoader.class) {
if (mInstance == null) {
mInstance = new SimpleImageLoader(config);
}
}
}
return mInstance;
}
/**
* 第二次获取单例
*
* @return
*/
public static SimpleImageLoader getInstance() {
if (mInstance == null) {
throw new UnsupportedOperationException("没有初始化");
}
return mInstance;
}
/**
* @param imageView
* @param uri file开头
*/
public void displayImage(ImageView imageView, String uri) {
displayImage(imageView, uri, null, null);
}
public void displayImage(ImageView imageView, String uri, Displayconfig displayconfig, ImageListener imageListener) {
//实例化一个请求
BitmapRequest bitmapRequest = new BitmapRequest(imageView, uri, displayconfig, imageListener);
// 添加到队列里边去
mRequestQueue.addRequest(bitmapRequest);
}
public static interface ImageListener {
void onComplete(ImageView imageView, Bitmap bitmap, String uri);
}
/**
* 获取到全局配置
*
* @return
*/
public ImageLoaderConfig getConfig() {
return config;
}
}
实现Loader加载逻辑 AbstarctLoader.java
public abstract class AbstarctLoader implements Loader {
//拿到用户自定义配置的缓存策略
private BitmapCache bitmapCache = SimpleImageLoader.getInstance().getConfig().getBitmapCache();
//拿到显示配置
private Displayconfig displayConfig = SimpleImageLoader.getInstance().getConfig().getDisplayconfig();
@Override
public void loadImage(BitmapRequest request) {
//从缓存中取到bitmap
Bitmap bitmap = bitmapCache.get(request);
if (bitmap == null) {
//显示默认加载图片
showLoadingImage(request);
//开始真正加载图片
bitmap = onLoad(request);
//缓存图片
cacheBitmap(request, bitmap);
}
deliveryToUIThread(request,bitmap);
}
/**
* 交给主线程显示
* @param request
* @param bitmap
*/
protected void deliveryToUIThread(final BitmapRequest request, final Bitmap bitmap) {
ImageView imageView = request.getImageView();
if(imageView!=null)
{
imageView.post(new Runnable() {
@Override
public void run() {
updateImageView(request, bitmap);
}
});
}
}
private void updateImageView(final BitmapRequest request, final Bitmap bitmap) {
ImageView imageView = request.getImageView();
//加载正常 防止图片错位
if(bitmap != null && imageView.getTag().equals(request.getImageUrl())){
imageView.setImageBitmap(bitmap);
}
//有可能加载失败
if(bitmap == null && request.getDisplayConfig()!=null&&request.getDisplayConfig().failImage!=-1){
imageView.setImageResource(displayConfig.failImage);
}
//监听
//回调 给圆角图片 特殊图片进行扩展
if(request.imageListener != null){
request.imageListener.onComplete(imageView, bitmap, request.getImageUrl());
}
}
private void cacheBitmap(BitmapRequest request, Bitmap bitmap) {
if (request != null && bitmap != null) {
synchronized (AbstarctLoader.class) {
bitmapCache.put(request, bitmap);
}
}
}
//抽象加载策略,因为加载网络图片和本地图片有差异
protected abstract Bitmap onLoad(BitmapRequest request);
private void showLoadingImage(BitmapRequest request) {
//指定了,显示配置
if (hasLoadingPlaceHolder()) {
final ImageView imageView = request.getImageView();
if (imageView != null) {
imageView.post(new Runnable() {
@Override
public void run() {
imageView.setImageResource(displayConfig.loadingImage);
}
});
}
}
}
protected boolean hasLoadingPlaceHolder() {
return (displayConfig != null && displayConfig.loadingImage > 0);
}
}
创建本地加载类 LocalLoader.java
public class LocalLoader extends AbstarctLoader {
@Override
protected Bitmap onLoad(BitmapRequest request) {
//得到本地图片的路径
final String path = Uri.parse(request.getImageUrl()).getPath();
File file = new File(path);
if (!file.exists()) {
return null;
}
BitmapDecoder decoder = new BitmapDecoder() {
@Override
protected Bitmap decodeBitmapWithOption(BitmapFactory.Options options) {
return BitmapFactory.decodeFile(path, options);
}
};
return decoder.decoderBitmap(ImageviewHelper.getImageViewWidth(request.getImageView()),
ImageviewHelper.getImageViewHeight(request.getImageView()));
}
}
实现网络加载逻辑 UrlLoader.java
public class UrlLoader extends AbstarctLoader {
@Override
protected Bitmap onLoad(final BitmapRequest request) {
//先下载 后读取
downloadImgByUrl(request.getImageUrl(), getCache(request.getImageUriMD5()));
//解码图片
BitmapDecoder bitmapDecoder = new BitmapDecoder() {
@Override
protected Bitmap decodeBitmapWithOption(BitmapFactory.Options options) {
//bitmap 对象值为空,因为读取的只是宽高
return BitmapFactory.decodeFile(getCache(request.getImageUriMD5()).getAbsolutePath(), options);
}
};
return bitmapDecoder.decoderBitmap(ImageviewHelper.getImageViewWidth(request.getImageView()),
ImageviewHelper.getImageViewHeight(request.getImageView()));
}
public static boolean downloadImgByUrl(String urlStr, File file) {
FileOutputStream fos = null;
InputStream is = null;
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
is = conn.getInputStream();
fos = new FileOutputStream(file);
byte[] buf = new byte[512];
int len = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
}
return false;
}
private File getCache(String unipue) {
File file = new File(Environment.getExternalStorageDirectory(), "ImageLoader");
if (!file.exists()) {
file.mkdir();
}
return new File(file, unipue);
}
当然如果你既不是本地的地址,也不是网络地址,就返回空的加载实现 NullLoader.java
public class NullLoader extends AbstarctLoader {
@Override
protected Bitmap onLoad(BitmapRequest request) {
return null;
}
}
创建一个加载管理类,把所有的加载类型管理,然后判断进行分发 LoaderManager.java
public class LoaderManager {
//缓存所有支持的Loader类型
private Map<String, Loader> mLoaderMap = new HashMap<>();
private static LoaderManager mInstance = new LoaderManager();
public static LoaderManager getInstance() {
return mInstance;
}
private LoaderManager() {
register("http", new UrlLoader());
register("https", new UrlLoader());
register("file", new LocalLoader());
}
private void register(String schema, Loader loader) {
mLoaderMap.put(schema, loader);
}
public Loader getLoader(String schema) {
if (mLoaderMap.containsKey(schema)) {
return mLoaderMap.get(schema);
}
return new NullLoader();
}
}
6、实现图片请求类 BitmapRequest.java
public class BitmapRequest implements Comparable<BitmapRequest> {
public BitmapRequest(ImageView imageView, String imageUrl, Displayconfig displayconfig, SimpleImageLoader.ImageListener imageListener) {
this.imageViewSoft = new SoftReference<>(imageView);
//设置可见的image的Tag为要下载的图片路径
imageView.setTag(imageUrl);
this.imageUrl = imageUrl;
this.imageListener = imageListener;
if (displayconfig != null)
this.displayconfig = displayconfig;
this.imageUriMD5 = MD5Utils.toMD5(imageUrl);
}
public BitmapRequest(ImageView imageView, String imageUrl, SimpleImageLoader.ImageListener imageListener) {
this.imageViewSoft = new SoftReference<>(imageView);
//设置可见的image的Tag为要下载的图片路径
imageView.setTag(imageUrl);
this.imageUrl = imageUrl;
this.imageListener = imageListener;
this.imageUriMD5 = MD5Utils.toMD5(imageUrl);
}
private Displayconfig displayconfig;
//持有ImageView的软应用
private SoftReference<ImageView> imageViewSoft;
//图片路径
private String imageUrl;
//MD5图片路径
private String imageUriMD5;
//下载完成监听
public SimpleImageLoader.ImageListener imageListener;
public String getImageUriMD5() {
return imageUriMD5;
}
//加载策略
private LoadPolicy loadPolicy = SimpleImageLoader.getInstance().getConfig().getLoadPolicy();
//优先级编号
private int serialNo;
public int getSerialNo() {
return serialNo;
}
public ImageView getImageView() {
return imageViewSoft.get();
}
public String getImageUrl() {
return this.imageUrl;
}
public void setSerialNo(int serialNo) {
this.serialNo = serialNo;
}
public Displayconfig getDisplayConfig() {
return displayconfig;
}
public LoadPolicy getLoadPolicy() {
return loadPolicy;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BitmapRequest that = (BitmapRequest) o;
if (serialNo != that.serialNo) return false;
return loadPolicy != null ? loadPolicy.equals(that.loadPolicy) : that.loadPolicy == null;
}
@Override
public int hashCode() {
int result = loadPolicy != null ? loadPolicy.hashCode() : 0;
result = 31 * result + serialNo;
return result;
}
//确定优先级
@Override
public int compareTo(BitmapRequest o) {
return loadPolicy.compareto(o, this);
}
}
实现请求队列 RequestQueue.java
public class RequestQueue {
/**
* 优先级阻塞式队列
* 多线程共享
* 生产效率和消费者效率差太远
* 优先级高的队列先被消费
* 每一个产品都有编号
*/
private BlockingQueue<BitmapRequest> mRequestsQueue = new PriorityBlockingQueue<>();
/**
* 转发器数量
*/
private int threadcount;
//一组转发器
private RequestDispatcher[] mDispatcher;
private AtomicInteger i = new AtomicInteger(0);
public RequestQueue(int threadcount) {
this.threadcount = threadcount;
}
/**
* 添加请求对象
*
* @param request
*/
public void addRequest(BitmapRequest request) {
//判断请求队列是否包含请求
if (!mRequestsQueue.contains(request)) {
//给请求进行编号
request.setSerialNo(i.incrementAndGet());
mRequestsQueue.add(request);
} else {
Log.w("", "请求已经存在 编号:" + request.getSerialNo());
}
}
/**
* 开启请求
*/
public void start() {
//先停止,在开启
stop();
startDispatchers();
}
private void startDispatchers() {
mDispatcher=new RequestDispatcher[threadcount];
for (int i=0;i<threadcount;i++){
RequestDispatcher dispatcher=new RequestDispatcher(mRequestsQueue);
mDispatcher[i]=dispatcher;
mDispatcher[i].start();
}
}
/**
* 停止请求
*/
public void stop() {
}
}
实现请求转发 RequestDispatcher.java
public class RequestDispatcher extends Thread {
//转发器 --------请求转发线程,不断从请求队列获取请求
//请求队列
private BlockingQueue<BitmapRequest> mRequestQueue;
public RequestDispatcher(BlockingQueue<BitmapRequest> mRequestQueue) {
this.mRequestQueue = mRequestQueue;
}
@Override
public void run() {
while (!isInterrupted()) {
try {
BitmapRequest request = mRequestQueue.take();
/**
* 处理请求对象
*/
Log.i("wxf","imageurl:------->"+request.getImageUrl());
String schema = pareSchema(request.getImageUrl());
//获取加载器
Loader loader = LoaderManager.getInstance().getLoader(schema);
Log.i("wxf","loader------->"+loader);
loader.loadImage(request);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private String pareSchema(String imageUrl) {
if (imageUrl.contains("://")) {
return imageUrl.split("://")[0];
} else {
Log.i("wxf", "不支持此类型");
}
return null;
}
}
7、实现图片压缩类 BitmapDecoder.java
public abstract class BitmapDecoder {
/**
* 压缩图片
* @param reqWidth
* @param reqheight
* @return 得到压缩后的图片
*/
public Bitmap decoderBitmap(int reqWidth, int reqheight) {
//初始化Options
BitmapFactory.Options options = new BitmapFactory.Options();
//得到宽高信息,设置为true不会读取整张图片到内存
options.inJustDecodeBounds = true;
decodeBitmapWithOption(options);
//计算图片缩放比例
caculateSapleSizeOptions(options, reqWidth, reqheight);
return decodeBitmapWithOption(options);
}
/**
* 计算缩放比
* @param options
* @param reqWidth
* @param reqHeight
*/
private void caculateSapleSizeOptions(BitmapFactory.Options options, int reqWidth, int reqHeight) {
//计算缩放的比例
//图片的原始宽高
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
// reqWidth ImageView的 宽
if (width > reqWidth || height > reqHeight) {
//宽高的缩放比例
int heightRatio = Math.round((float) height / (float) reqHeight);
int widthRatio = Math.round((float) width / (float) reqWidth);
//有的图是长图、有的是宽图
inSampleSize = Math.max(heightRatio, widthRatio);
}
//全景图
//当inSampleSize为2,图片的宽与高变成原来的1/2
//options.inSampleSize = 2
options.inSampleSize = inSampleSize;
//每个像素2个字节
options.inPreferredConfig = Bitmap.Config.RGB_565;
//Bitmap占用内存 true
options.inJustDecodeBounds = false;
//当系统内存不足时可以回收Bitmap
options.inPurgeable = true;
options.inInputShareable = true;
}
protected abstract Bitmap decodeBitmapWithOption(BitmapFactory.Options options);
}
实现ImageView控件宽高获取 ImageviewHelper.java
public class ImageviewHelper {
private static int DEFAULT_WIDTH = 200;
private static int DEFAULT_HEIGHT = 200;
public static int getImageViewWidth(ImageView imageView) {
if (imageView != null) {
ViewGroup.LayoutParams params = imageView.getLayoutParams();
int width = 0;
if (params != null && params.width != ViewGroup.LayoutParams.WRAP_CONTENT) {
width = imageView.getWidth();
}
if (width <= 0 && params != null) {
width = params.width;
}
if (width <= 0) {
width = getImageViewFieldValue(imageView, "mMaxWidth");
}
return width;
}
return DEFAULT_WIDTH;
}
public static int getImageViewHeight(ImageView imageView) {
if (imageView != null) {
ViewGroup.LayoutParams params = imageView.getLayoutParams();
int height = 0;
if (params != null && params.height != ViewGroup.LayoutParams.WRAP_CONTENT) {
height = imageView.getHeight();
}
if (height <= 0 && params != null) {
height = params.height;
}
if (height <= 0) {
height = getImageViewFieldValue(imageView, "mMaxHeight");
}
return height;
}
return DEFAULT_HEIGHT;
}
private static int getImageViewFieldValue(ImageView imageView, String fieldName) {
try {
Field field = ImageView.class.getDeclaredField(fieldName);
field.setAccessible(true);
int fieldValue = (int) field.get(imageView);
if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
return fieldValue;
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return 0;
}
}
MD5Utils帮助类
public class MD5Utils {
private static MessageDigest digest;
static {
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
Log.d("wxf", "md5 算法不支持!");
}
}
/**
* MD5加密
*
* @param key
* @return
*/
public static String toMD5(String key) {
if (digest == null) {
return String.valueOf(key.hashCode());
}
//更新字节
digest.update(key.getBytes());
//获取最终的摘要 十进制的 12345678/ABCD1245
return convert2HexString(digest.digest());
}
/**
* 转为16进制字符串
*
* @param bytes
* @return
*/
private static String convert2HexString(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (byte b : bytes) {
//->8->08
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
}
8、调用
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private MyAdapter myAdapter;
private List<Entity> mList = new ArrayList<>();
SimpleImageLoader simpleImageLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageLoaderConfig config = new ImageLoaderConfig.Builder()
.setThreadCount(3)
.setLoadpolicy(new ReversePolicy())
.setCachePlicy(new DoubleCache(this))
.setLoadingImage(R.mipmap.ic_launcher)
.setFailImage(R.mipmap.ic_launcher).build();
simpleImageLoader = SimpleImageLoader.getInstance(config);
for (int i = 0; i < 10; i++) {
Entity entity = new Entity();
entity.name = i + "fsfdsdfsafdsfsdf";
mList.add(entity);
}
myAdapter = new MyAdapter(mList);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
recyclerView.setAdapter(myAdapter);
}
private class Entity {
public String url;
public String name;
}
private class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Entity> tempList;
public MyAdapter(List<Entity> mList) {
this.tempList = mList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_newandrecommendlesson, parent, false);
return new myViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((myViewHolder) holder).textView.setText("" + tempList.get(position).name);
simpleImageLoader.displayImage(((myViewHolder) holder).imageView, Images[position]);
}
@Override
public int getItemCount() {
return tempList.size();
}
}
private class myViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public ImageView imageView;
public myViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.item_newAndRecommendLesson_textView_title);
imageView = (ImageView) itemView.findViewById(R.id.item_newAndRecommendLesson_imageView_pic);
}
}
private String[] Images = {
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531129921916&di=13350c1a58f32683cfc90185f776d76f&imgtype=0&src=http%3A%2F%2Fpic-cdn.35pic.com%2F58pic%2F13%2F19%2F82%2F95g58PICtAm_1024.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130014832&di=57eec36f70f423eb3818e9cb8f4983c8&imgtype=0&src=http%3A%2F%2Ffa.topitme.com%2Fa%2F15%2F92%2F11216657698a59215ao.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130111946&di=55862e85879063bb85b76581b2b1b9dd&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F15%2F40%2F27%2F49B58PICXHQ_1024.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130126651&di=c28d13fab05f624522ab151241d6cb7d&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F12%2F29%2F66%2F40G58PIC9bI.jpg",
"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1220481886,24258781&fm=27&gp=0.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130151235&di=31bfcab8733a3cba6b8f3e31efc17b09&imgtype=0&src=http%3A%2F%2Fdepot.nipic.com%2Ffile%2F20160628%2F21447645_11093515769.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130198048&di=f9b8f99097970275df3905ea6e919f3b&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F13%2F14%2F93%2F70w58PIChtV_1024.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130289265&di=e4cfbb4d53acfd1340180168bf67e23e&imgtype=0&src=http%3A%2F%2Fimg15.3lian.com%2F2015%2Ff2%2F159%2Fd%2F95.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130307728&di=1e1daaa961b9723c11d961ff8b017f33&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F86d6277f9e2f07083cebe627e224b899a901f22f.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130316514&di=060abcc3e117b44d3432bed4634c0b81&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2Fcefc1e178a82b901ceb88214788da9773912ef84.jpg"
};
}
注意:1、图片地址用MD5编码之后可是预防非法字符
2、别忘了添加读取和网络权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3、DiskLruCache加载类的实现网上代码很多都是通用的,也可以在我的资源中下载
4、这个还没有实现图片的取消等,那个应该考虑Activity和Fragment然后根据生命周期去做相应的取消