自定义ImageLoader

2022-03-15  本文已影响0人  itbird01

近期看了一些设计模式相关的书籍,突然有了一个想法,借助所学,去实现一个图片加载框架。

1.UML设计

image.png

从图中可以看到面向对象的几大设计原则
1)依赖倒置原则:高层模块(ImageLoader)只依赖于接口or抽象类(ImageCache),不依赖具体的实现类(DiskImageCache、MemoryImageCache等具体的实现类)
2)单一职责原则:加载业务、不同的缓存业务相分离,实现了解耦、分离
3)开闭原则:修改不同的缓存策略、用户不同的自定义缓存策略,都可以通过继承ImageCache接口类实现具体的缓存类,而且过程中,ImageLoader、ImageCache不再需要改动,只需改动上层调用处(Activity)
4)里氏代换原则:基类出现的地方,都可以通过子类来替代,在ImageLoader内部只有ImageCache的基类对象存在,在activity中调用时,ImageLoader内部传入具体的实现类(DiskImageCache、Memory...)
5)接口隔离原则:使接口功能尽可能的少、分离,此处无体现,当然,如果我们有更多复杂的场景和需求,不要把所有功能接口都写在ImageLoader内部,而是根据不同的业务类型去封装不同的业务接口,实现接口隔离
6)迪米特原则(最小知道原则):一个类对另外一个类的了解,尽可能的少,此处未体现

2.代码实现

ImageCache

package com.itbird.imageloader;

import android.graphics.Bitmap;

/**
 * Created by itbird on 2022/2/28
 */
public interface ImageCache {
    Bitmap get(String url);

    void put(String url, Bitmap bitmap);

    void remove(String url);
}

DiskImageCache

package com.itbird.imageloader;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.util.LruCache;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by itbird on 2022/2/28
 */
public class DiskImageCache implements ImageCache {
    @Override
    public Bitmap get(String url) {
        return BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + url.substring(url.lastIndexOf("/")));
    }

    @Override
    public void put(String url, Bitmap bitmap) {
        File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + url.substring(url.lastIndexOf("/")));
        Log.d("itbird", file.getAbsolutePath());
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void remove(String url) {
        if (TextUtils.isEmpty(url)) {
            return;
        }

        File file = new File("/sdcard/Pictures/" + url);
        if (file == null || !file.exists()) {
            return;
        }
        file.delete();
    }
}

MemoryImageCache

package com.itbird.imageloader;

import android.graphics.Bitmap;
import android.util.LruCache;

/**
 * Created by itbird on 2022/2/28
 */
public class MemoryImageCache implements ImageCache {
    LruCache<String, Bitmap> bitmapLruCache;

    public MemoryImageCache() {
        bitmapLruCache = new LruCache<>(10);
    }

    @Override
    public Bitmap get(String url) {
        return bitmapLruCache.get(url);
    }

    @Override
    public void put(String url, Bitmap bitmap) {
        bitmapLruCache.put(url, bitmap);
    }

    @Override
    public void remove(String url) {
        bitmapLruCache.remove(url);
    }
}

MymageCache

package com.itbird.imageloader;

import android.graphics.Bitmap;

/**
 * Created by itbird on 2022/2/28
 */
public class MymageCache implements ImageCache {
    MemoryImageCache memoryImageCache;
    DiskImageCache diskImageCache;

    public MymageCache() {
        memoryImageCache = new MemoryImageCache();
        diskImageCache = new DiskImageCache();
    }

    @Override
    public Bitmap get(String url) {
        Bitmap bitmap = memoryImageCache.get(url);
        if (bitmap != null) {
            return bitmap;
        }

        bitmap = diskImageCache.get(url);
        if (bitmap != null) {
            return bitmap;
        }
        return null;
    }

    @Override
    public void put(String url, Bitmap bitmap) {
        memoryImageCache.put(url, bitmap);
        diskImageCache.put(url, bitmap);
    }

    @Override
    public void remove(String url) {
        memoryImageCache.remove(url);
        diskImageCache.remove(url);
    }
}

ImageLoader

package com.itbird.imageloader;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import androidx.annotation.NonNull;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by itbird on 2022/2/28
 */
public class ImageLoader {
    private volatile static ImageLoader mInstance;
    private ImageCache mImageCache;
    ExecutorService mExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private WeakReference<Context> mContext;
    private Handler mHandler;

    public static ImageLoader getInstance(Context context) {
        if (mInstance == null) {
            synchronized (ImageLoader.class) {
                if (mInstance == null) {
                    mInstance = new ImageLoader(context);
                }
            }
        }
        return mInstance;
    }

    private ImageLoader(Context context) {
        mContext = new WeakReference<>(context);
        mHandler = new Handler(context.getMainLooper());
    }

    public void setImageLCache(ImageCache imageLCache) {
        mImageCache = imageLCache;
    }


    public void setImageView(String url, ImageView imageView) {
        if (TextUtils.isEmpty(url) || imageView == null) {
            return;
        }
        Bitmap bitmap = mImageCache.get(url);
        if (bitmap == null) {
            imageView.setTag(url);
            downloadImage(url, imageView);
        } else {
            imageView.setImageBitmap(bitmap);
        }
    }

    private void downloadImage(String url, ImageView imageView) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = downloadUrlBitmap(url);
                if (TextUtils.equals((CharSequence) imageView.getTag(), url)) {
                    Log.e("itbird", "" + bitmap.getByteCount());
                    //cackback主线程
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            imageView.setImageBitmap(bitmap);
                        }
                    });
                }
                if (mImageCache != null) {
                    mImageCache.put(url, bitmap);
                }
            }
        });
    }

    private Bitmap downloadUrlBitmap(String urlString) {
        HttpURLConnection urlConnection = null;
        BufferedInputStream in = null;
        Bitmap bitmap = null;
        try {
            final URL url = new URL(urlString);
            urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
            bitmap = BitmapFactory.decodeStream(in);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
            byte[] bytes = bos.toByteArray();
            bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        } catch (final IOException e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            try {
                if (in != null) {
                    in.close();
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
        return bitmap;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读