写在前面
毕业一个月以来,一直没有好好的整理自己,每天都过的浑浑噩噩,直到昨天,群里的朋友拿到了一个20K的offer,看了看他的面试题,才知道自己的差距到底有多大 => 谨以此来告诫自己要好好的努力
正文
博客的目的 -> 总结和积累
博客的难度 -> 求大佬轻虐
例子
单纯的写一个网络图片加载器
public class ImageLoader {
//这个类的功能主要是用于加载网络图片
//图片缓存
LruCache<String, Bitmap> mImageCache;
//线程池,线程数量为CPU的数量
ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public ImageLoader() {
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 url, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
}
};
}
/**
* 展示图片
*
* @param url
* @param imageView
*/
public void disPlayImage(final String url, final ImageView imageView) {
//设置图片标记
imageView.setTag(url);
//使用Submit会返回一个Future对象,可以判断Runnable是否结束执行
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);
}
});
}
/**
* 网络加载图片
*
* @param imageUrl
* @return
*/
private 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;
}
}
分析
在这里要考虑以下几点
1. 缓存池的设置
2. 线程池的加载
3. 相关标记的判断
==> 创建缓存池 -> 判断缓存池是否存在图片 -> 存在则加载;不存在则网络下载,并且加入到缓存池中
但是在设计模式上,我们会发现以下问题:
1. 我们的ImageLoader类其实负责的不单单的是网络图片的加载,在其中还涉及到了缓存的预处理
2. 在加载图片的时候,没有去判断缓存池中的图片
3. 代码的耦合性很严重
4. 如果去扩展,那么说扩展起来很复杂
在这里,我们引入一个单一职责原则
一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。
通过引入单一职责原则,让我们的代码的耦合性降低,我们的类中的职责可以单一,那么说上述的代码可以分为两个类:缓存处理类、图片加载类
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 url, 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);
}
}
public class ImageLoader {
ImageCache mImageCache = new ImageCache();
ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public void disPlayImage(final String url, final ImageView imageView) {
Bitmap bitmap = mImageCache.get(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
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);
}
});
}
private Bitmap downLoadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
}
通过上述代码,我们实现了:
1. ImageLoader只负责图片加载的逻辑
2. ImageCache只负责图片缓存的逻辑