Android移动架构汇总
##一、框架设计需求
根据用户需求可以灵活配置(建造者模式)
支持高并发,图片加载的优先级
支持可以选择不同的加载策略,对加载策略进行扩展
二级缓存 加载图片时内存中已经加载了,则从内存中加载,不存在去外置卡中加载,外置还不存在则从网络下载
并对缓存策略可以扩展
支持从加载过程中显示默认加载图片
支持加载失败时 显示默认错误图片
图片显示自适应。从网络加载下来的图片经最佳比例压缩后显示
不能失真变形
支持请求转发,下载
用到的模式:
生产者 消费者模式
建造者模式
单例模式
模板方法模式
策略模式
用到的知识点
内存缓存 LruCache技术
硬盘缓存技术DiskLruCache技术
图片下载时请求转发
##二、架构图
##三 、代码
demo地址:https://gitee.com/YuBaoZi/FangImageLoaderTuPianJiaZaiKuangJia
###1缓存策略
####1)定义图片缓存接口
public interface BitmapCache {
/**
* 缓存bitmap
* @param bitmap
*/
void put(BitmapRequest request, Bitmap bitmap);
/**
* 通过请求取Bitmap
* @param request
* @return
*/
Bitmap get(BitmapRequest request);
/**
* 移除缓存
* @param request
*/
void remove(BitmapRequest request);
}
####2)使用DiskLruCache定义硬盘缓存,这里DisLruCache直接拿来用,不做过多介绍
public class DiskCache implements BitmapCache {
private static DiskCache mDiskCache;
//缓存路径
private String mCacheDir = "Image";
//MB
private static final int MB = 1024 * 1024;
//jackwharton的杰作
private DiskLruCache mDiskLruCache;
private DiskCache(Context context)
{
iniDiskCache(context);
}
public static DiskCache getInstance(Context context) {
if(mDiskCache==null)
{
synchronized (DiskCache.class)
{
if(mDiskCache==null)
{
mDiskCache=new DiskCache(context);
}
}
}
return mDiskCache;
}
private void iniDiskCache(Context context) {
//得到缓存的目录
File directory=getDiskCache(mCacheDir,context);
if(!directory.exists())
{
directory.mkdir();
}
try {
//最后一个参数 指定缓存容量
mDiskLruCache=DiskLruCache.open(directory,1,1,50*MB);
} catch (IOException e) {
e.printStackTrace();
}
}
private File getDiskCache(String mCacheDir, Context context) {
String cachePath;
//默认缓存路径
return new File(Environment.getExternalStorageDirectory(),mCacheDir);
}
@Override
public void put(BitmapRequest request, Bitmap bitmap) {
DiskLruCache.Editor edtor=null;
OutputStream os=null;
try {
//路径必须是合法字符
edtor=mDiskLruCache.edit(request.getImageUriMD5());
os=edtor.newOutputStream(0);
if(persistBitmap2Disk(bitmap,os))
{
edtor.commit();
}else {
edtor.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();
}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();
}
}
}
####3)内存缓存
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());
}
}
####4)双缓存
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);
}
}
###2 加载策略
public interface LoadPolicy {
/**
* 两个BItmapRequest进行优先级比较
* @param request1
* @param request2
* @return
*/
int compareto(BitmapRequest request1,BitmapRequest request2);
}
public class ReversePolicy implements LoadPolicy {
@Override
public int compareto(BitmapRequest request1, BitmapRequest request2) {
return request2.getSerialNo()-request1.getSerialNo();
}
}
public class SerialPolicy implements LoadPolicy {
@Override
public int compareto(BitmapRequest request1, BitmapRequest request2) {
return request1.getSerialNo()-request2.getSerialNo();
}
}
###3 加载配置
public class DisplayConfig {
/**
* 加载过程中默认显示的图片Id
*/
public int loadingImage=-1;
//加载失败显示的图片
public int faildImage=-1;
}
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()
{
}
/**
* 建造者模式
* 和AlterDialog建造过程类似
*/
public static class Builder
{
private ImageLoaderConfig config;
public Builder()
{
config=new ImageLoaderConfig();
}
/**
* 设置缓存策略
* @param bitmapCache
* @return
*/
public Builder setCachePolicy(BitmapCache bitmapCache)
{
config.bitmapCache=bitmapCache;
return this;
}
/**&
* 设置加载策略
* @param loadPolicy
* @return
*/
public Builder setLoadPolicy(LoadPolicy loadPolicy)
{
config.loadPolicy=loadPolicy;
return this;
}
/**
* 设置线程个数
* @param count
* @return
*/
public Builder setThreadCount(int count)
{
config.threadCount=count;
return this;
}
/**
* 设置加载过程中的图片
* @param resID
* @return
*/
public Builder setLoadingImage(int resID)
{
config.displayConfig.loadingImage=resID;
return this;
}
/**
* 设置加载过程中的图片
* @param resID
* @return
*/
public Builder setFaildImage(int resID)
{
config.displayConfig.faildImage=resID;
return this;
}
public ImageLoaderConfig build()
{
return config;
}
}
public BitmapCache getBitmapCache() {
return bitmapCache;
}
public LoadPolicy getLoadPolicy() {
return loadPolicy;
}
public int getThreadCount() {
return threadCount;
}
public DisplayConfig getDisplayConfig() {
return displayConfig;
}
}
###4 定义具体加载器,实现图片加载
public interface Loader {
/**
* 加载图片
* @param request
*/
void loadImage(BitmapRequest request);
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 && displayConfig!=null&&displayConfig.faildImage!=-1){
imageView.setImageResource(displayConfig.faildImage);
}
//监听
//回调 给圆角图片 特殊图片进行扩展
if(request.imageListener != null){
request.imageListener.onComplete(imageView, bitmap, request.getImageUrl());
}
}
/**
* 缓存图片
* @param request
* @param bitmap
*/
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);
/**
* 加载前显示的图片
* @param request
*/
protected 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);
}
}
public class NullLoader extends AbstarctLoader {
@Override
protected Bitmap onLoad(BitmapRequest request) {
return null;
}
}
public class UrlLoader extends AbstarctLoader {
@Override
protected Bitmap onLoad(final BitmapRequest request) {
//先下载 后读取
downloadImgByUrl(request.getImageUrl(),getCache(request.getImageUriMD5()));
BitmapDecoder decoder=new BitmapDecoder() {
@Override
public Bitmap decodeBitmapWithOption(BitmapFactory.Options options) {
return BitmapFactory.decodeFile(getCache(request.getImageUriMD5()).getAbsolutePath(),options);
}
};
return decoder.decodeBitmap(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);
}
}
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
public Bitmap decodeBitmapWithOption(BitmapFactory.Options options) {
return BitmapFactory.decodeFile(path,options);
}
};
return decoder.decodeBitmap(ImageViewHelper.getImageViewWidth(request.getImageView())
,ImageViewHelper.getImageViewHeight(request.getImageView()));
}
}
public class LoaderManager {
//缓存所有支持的Loader类型
private Map<String ,Loader> mLoaderMap=new HashMap<>();
private static LoaderManager mInstance=new LoaderManager();
private LoaderManager()
{
register("http",new UrlLoader());
register("https",new UrlLoader());
register("file",new LocalLoader());
}
public static LoaderManager getInstance()
{
return mInstance;
}
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();
}
}
###4 网络请求
public class BitmapRequest implements Comparable<BitmapRequest> {
//持有imageview的软引用
private SoftReference<ImageView> imageViewSoft;
//图片路径
private String imageUrl;
//MD5的图片路径
private String imageUriMD5;
//下载完成监听
public SimpleImageLoader.ImageListener imageListener;
private DisplayConfig displayConfig;
public BitmapRequest(ImageView imageView,String imageUrl,DisplayConfig displayConfig,
SimpleImageLoader.ImageListener imageListener) {
this.imageViewSoft=new SoftReference<ImageView>(imageView);
//设置可见的Image的Tag,要下载的图片路径
imageView.setTag(imageUrl);
this.imageUrl=imageUrl;
this.imageUriMD5= MD5Utils.toMD5(imageUrl);
if(displayConfig!=null)
{
this.displayConfig=displayConfig;
}
this.imageListener = imageListener;
}
//加载策略
private LoadPolicy loadPolicy= SimpleImageLoader.getInstance().getConfig().getLoadPolicy();
/**
* 编号
*/
private int serialNo;
public int getSerialNo() {
return serialNo;
}
public void setSerialNo(int serialNo) {
this.serialNo = serialNo;
}
@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;
}
public ImageView getImageView()
{
return imageViewSoft.get();
}
public String getImageUrl() {
return imageUrl;
}
public String getImageUriMD5() {
return imageUriMD5;
}
public DisplayConfig getDisplayConfig() {
return displayConfig;
}
public LoadPolicy getLoadPolicy() {
return loadPolicy;
}
@Override
public int compareTo(BitmapRequest o) {
return loadPolicy.compareto(o,this);
}
}
/**
* 转发器
* 请求转发线程 不断从请求队列中获取请求
*/
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();
/**
* 处理请求对象
*/
String schema=parseSchema(request.getImageUrl());
//获取加载器
Loader loader= LoaderManager.getInstance().getLoader(schema);
loader.loadImage(request);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private String parseSchema(String imageUrl) {
if(imageUrl.contains("://"))
{
return imageUrl.split("://")[0];
}
else
{
Log.i(TAG,"不支持此类型");
}
return null;
}
}
public class RequestQueue {
/**
*阻塞式队列
* 多线程共享
* 生产效率 和消费效率想查太远了。
* disPlayImage()
* 使用优先级队列
* 优先级高的队列先被消费
* 每 一个产品都有编号
*/
private BlockingQueue<BitmapRequest> mRequestQueue=new PriorityBlockingQueue<>();
/**
* 转发器的数量
*/
private int threadCount;
//i++ ++i 能 1 不能 2
private AtomicInteger i=new AtomicInteger(0);
//一组转发器
private RequestDispatcher[] mDispachers;
public RequestQueue(int threadCount) {
this.threadCount = threadCount;
}
/**
* 添加请求对象
* @param request
*/
public void addRequest(BitmapRequest request)
{
//判断请求队列是否包含请求
if(!mRequestQueue.contains(request))
{
//给请求进行编号
request.setSerialNo(i.incrementAndGet());
mRequestQueue.add(request);
}else
{
Log.i(TAG,"请求已经存在 编号:"+request.getSerialNo());
}
}
/**
* 开启请求
*/
public void start()
{
//先停止
stop();
startDispatchers();
}
/**
* 开启转发器
*/
private void startDispatchers() {
mDispachers=new RequestDispatcher[threadCount];
for(int i=0;i<threadCount;i++)
{
RequestDispatcher p=new RequestDispatcher(mRequestQueue);
mDispachers[i]=p;
mDispachers[i].start();
}
}
/**
* 停止
*/
public void stop()
{
}
}
###5 工具类
public abstract class BitmapDecoder {
public Bitmap decodeBitmap(int reqWidth,int reqHeight)
{
//初始化options
BitmapFactory.Options options=new BitmapFactory.Options();
//只需要读取图片宽高信息,无需将整张图片加载到内存 inJustDecodeBounds设置true
options.inJustDecodeBounds=true;
//根据options加载Bitmap 抽象
decodeBitmapWithOption(options);
//计算图片缩放比例
calculateSampleSizeWithOption(options,reqWidth,reqHeight);
return decodeBitmapWithOption(options);
}
/**
* 计算图片缩放的比例
* @param options
* @param reqWidth
* @param reqHeight
*/
private void calculateSampleSizeWithOption(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;
}
public abstract Bitmap decodeBitmapWithOption(BitmapFactory.Options options);
}
public class ImageViewHelper {
//默认的图片宽高
private static int DEFAULT_WIDTH = 200;
private static int DEFAULT_HEIGHT = 200;
/**
* 获取ImageView控件的宽度
* 1.getWidth(绘制完成,如果视图没有绘制完成没有值)
* 2.layout_width(有可能设置的是WRAP_CONTENT)
* 3.maxWidth
* 拿到ImageView的宽高
* @param imageView
* @return
*/
public static int getImageViewWidth(ImageView imageView){
if(imageView != null){
// imageView.getWidth()==0;
LayoutParams params = imageView.getLayoutParams();
int width = 0;
if(params != null && params.width != 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;
}
/**
* 获取图片的高度
* @param imageView
* @return
*/
public static int getImageViewHeight(ImageView imageView){
if(imageView != null){
LayoutParams params = imageView.getLayoutParams();
int height = 0;
if(params != null && params.height != LayoutParams.WRAP_CONTENT){
height = imageView.getWidth();
}
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 = (Integer)field.get(imageView);
if(fieldValue > 0 && fieldValue < Integer.MAX_VALUE){
return fieldValue;
}
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}
public class MD5Utils {
private static MessageDigest digest;
static{
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
Log.d("jason", "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();
}
}
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 http: file 开头
*/
public void displayImage(ImageView imageView,String uri)
{
displayImage(imageView,uri,null,null);
}
/**
* 重载
* @param imageView
* @param uri
* @param displayConfig
* @param imageListener
*/
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{
/**
*
* @param imageView
* @param bitmap
* @param uri
*/
void onComplete(ImageView imageView, Bitmap bitmap,String uri);
}
/**
* 拿到全局配置
* @return
*/
public ImageLoaderConfig getConfig() {
return config;
}
}
###6 使用
public class MainActivity extends AppCompatActivity {
SimpleImageLoader imageLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
GridView listview = (GridView) findViewById(R.id.listview);
listview.setAdapter(new MyAdapter(this));
//配置
ImageLoaderConfig.Builder build = new ImageLoaderConfig.Builder();
build.setThreadCount(3) //线程数量
.setLoadPolicy(new ReversePolicy()) //加载策略
.setCachePolicy(new DoubleCache(this)) //缓存策略
.setLoadingImage(R.drawable.loading)
.setFaildImage(R.drawable.not_found);
ImageLoaderConfig config = build.build();
//初始化
imageLoader = SimpleImageLoader.getInstance(config);
}
class MyAdapter extends BaseAdapter {
private LayoutInflater inflater;
public MyAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return imageThumbUrls.length;
}
@Override
public Object getItem(int position) {
return imageThumbUrls[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View item = inflater.inflate(R.layout.item, null);
ImageView imageView = (ImageView) item.findViewById(R.id.iv);
//请求图片
imageLoader.displayImage(imageView, imageThumbUrls[position]);
return item;
}
}
public final static String[] imageThumbUrls =new String[] {
"https://img-my.csdn.net/uploads/201407/26/1406383299_1976.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383291_6518.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383291_8239.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383290_9329.jpg",//DB123421AC
"https://img-my.csdn.net/uploads/201407/26/1406383290_1042.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383275_3977.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383265_8550.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383264_3954.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383264_4787.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383264_8243.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383248_3693.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383243_5120.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383242_3127.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383242_9576.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383242_1721.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383219_5806.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383214_7794.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383213_4418.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383213_3557.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383210_8779.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383172_4577.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383166_3407.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383166_2224.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383166_7301.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383165_7197.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383150_8410.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383131_3736.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383130_5094.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383130_7393.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383129_8813.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383100_3554.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383093_7894.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383092_2432.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383092_3071.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383091_3119.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383059_6589.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383059_8814.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383059_2237.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383058_4330.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383038_3602.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382942_3079.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382942_8125.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382942_4881.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382941_4559.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382941_3845.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382924_8955.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382923_2141.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382923_8437.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382922_6166.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382922_4843.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382905_5804.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382904_3362.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382904_2312.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382904_4960.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382900_2418.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382881_4490.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382881_5935.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382880_3865.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382880_4662.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382879_2553.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382862_5375.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382862_1748.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382861_7618.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382861_8606.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382861_8949.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382841_9821.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382840_6603.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382840_2405.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382840_6354.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382839_5779.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382810_7578.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382810_2436.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382809_3883.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382809_6269.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382808_4179.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382790_8326.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382789_7174.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382789_5170.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382789_4118.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382788_9532.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382767_3184.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382767_4772.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382766_4924.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382766_5762.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406382765_7341.jpg" };
}