自定义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;
}
}