Android源码设计模式解析与实战(Based on Lollipop) 第一章 读书笔记

来源:互联网 发布:网络安全法发布的意义 编辑:程序博客网 时间:2024/05/20 13:16

正巧这一章讲的就是图片加载器,和我的项目类似,于是我就读了这一章的内容。

首先Android开发涉及Java语言,程序中的抽象、接口、六大原则、23种设计模式等名词,这一些就像书中的小民,我已经晕头转向。

ImageCache.java

public class ImageLoader{    ImageCache mImageCache=new ImageChache();    ExecutorService mExecutorService=executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());    public void displayImage(final String url,final ImageView imageView){        Bitmap bitmap=ImageCache.get(url);        return;    }    imageView.setTag(url);    mExecutorService.submit(new Runnable(){        @Override         public void run(){            Bitmap bitmap=downloadImage(url);            if(bitmap==null){                return;            }            if(imageView.getTag().equals(url)){                imageView.setImageBitmap(bitmap);            }            mImageCache.put(url,bitmap);        }    });    public Bitmap downloadImage(String imageUrl){        Bitmap bitmap=null;        try{            URL url=new URL(imageUrl);            final HttpURLConnection conn(HttpURLConnection)url.openConnection();            bitmap=BitmapFactory.decodeStream(conn.getInputStream);            conn.disconnect();        }catch(Exception e){            e.printStackTrace();        }        return bitmap;    }}

ImageCache.java

public class ImageCache{    LruCache<String,Bitmap> mImageCache;    public ImageCache(){        initImageCache();    }    private void initImageCache(){        final int maxMemory=(int)(Runtime.getRuntime().maxMemory()/1024);        final int cacheSize=maxMemory/4;        mImageCache=new LruCache<String,Bitmap>(cacheSize){            @Override            protected int sizeOf(String key,Bitmap bitmap){                return bitmap.getRowBytes()*bitmap.getHeight()/1024;            }        };    }    public void put(String url,Bitmap bitmap){        mImageCache.put(url,bitmap);    }    public Bitmap get(String url){        return mImageCache.get(url);    }}

UML类图


应用的是单一模式,让ImageLoader一拆为二,ImageLoader只负责图片加速的逻辑,而ImageCache只负责处理图片换春的逻辑。这样ImageLoader的代码量就变少了。


首先写一个双缓存类DoubleCache,具体代码如下:

public class DoubleCache {    ImageCache mMemoryCache=new ImageCache();    DiskCache mDiskCache=new DiskCache();    public Bitmap get(String url){        Bitmap bitmap=mMemoryCache.get(url);        if(bitmap==null){            bitmap=mDiskCache.get(url);        }        return bitmap;    }    public void put(String url,Bitmap bmp){        mMemoryCache.put(url,bmp);        mDiskCache.put(url,bmp);    }}

首先缓存优先使用内存缓存,如果内存缓存没有图片再使用SD卡缓存,如果SD卡也没有图片缓存最后才从网络获取。

然后是最新的ImageLoader:

public class ImageLoader{    ImageCache mIamgeCache=new IamgeCache();    DiskCache mDiskCache=new DiskCache();    DoubleCache mDoubleCache=newDoubleCache();    boolean isUseDiskCache=false;    boolean isUseDoubleCache=false;    ExecutorService mExecutorService=executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());        public void displayImage(final String url,final ImageView imageView){        Bitmap bitmap=null;        if(isUseDoubleCache){            bmp=mDoubleCache.get(url);        }else if(isUseDiskCache){            bmp=mDiskCache.get(url);        }else{            bmp=mImageCache.get(url);        }                if(bmp!=null) {            imageView.setImageBitmap(bmp);        }    }    public void useDiskCache(boolean useDiskCache){        isUseDiskCache=useDiskcache;    }        public void useDoubleCache(boolean useDoubleCache){        isUseDoubleCache=useDoubleCache;    }}

但是问题是ImageLoader中有大量的if-else判断语句,通过这些判断来确定使用那种缓存。随着这些逻辑的引入,代码变得越来越复杂、脆弱,如果一旦写错某个if条件,那么就要花更多时间来排除,整个ImageLoader类也会变得越来越臃肿。

于是便提出了下面的UML图:


于是便将ImageLoader类重构:

public class ImageLoader{    ImageCache mIamgeCache=new IamgeCache();    ExecutorService mExecutorService=executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());    public void setImageCache(ImageCache cache){        mImageCache=cache;    }    public void displayImage(String imageUrl,ImageView imageView){        Bitmap bitmap=mImageCache.get(imageUrl);        if(bitmap!=null){            imageView.setImageBitmap(bitmap);            return;        }        submitLoadRequest(imageUrl,imageView);    }    private void submitLoadRequest(final String imageUrl,fianl Imageview imageView){        imageView.setTag(imageUrl);        mExecutorService.submit(new Runnable(){           @Override            public void run(){               Bitmap bitmap=downloadImage(imageUrl);               if(bitmap==null){                   return;               }               if(imageView.getTag().equals(imageUrl)){                   imageView.setImageBitmap(bitmap);               }           }        });    }    public Bitmap downloadImage(String imageUrl){        Bitmap bitmap=null;        try{            URL url=new URL(imageUrl);            final HttpURLConnection conn=(HttpURLConnection) url.openConnection();            conn.discount();        }catch(Exception e){            e.printStackTrace();        }        return bitmap;    }}

将原来的ImageCache改为接口:

public interface ImageCache{    public void put(String url,Bitmap bitmap);    public Bitmap get(String url);}

软件需要变化时,需要通过扩展的方式来实现变化,而不是反复的修改。“应该尽量”,OCP原则并不是绝对不可以修改原始类的。当原有的代码完全不适合扩展时,应该尽早地重构,以便使代码恢复到正常的”进化“过程。

里氏替换原则

Liskov Substitution Principle


示例代码:

public class Windows {    public void show(View child){        child.show();    }}public abstract class View{    public abstract void draw();    public void measure(int width,int height){        //测量视图大小    }}publlic class Button extends View{    public void draw(){        //绘制按钮    }}public class TextView extends View{    public void draw(){        //绘制文本    }}


单一职责 开闭原则 里氏替换原则 接口隔离 依赖倒置(依赖反转)定义为SOLID原则。

Law of Demeter

最少知识原则


0 0