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

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

首先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

最少知识原则


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值