移动架构36

xiaoxiao2021-02-28  38

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" }; }
转载请注明原文地址: https://www.6miu.com/read-250235.html

最新回复(0)