#####藉此也瞭解RxJava2的對應操做符的使用。git
項目Git地址 github.com/GenialSir/I…github
1,完成後圖片庫調用方式:數據庫
RxImageLoader.with(this).load("Link").into(ImageView);
複製代碼
2,首先建立RxImageLoader,採用單例模式,代碼以下:緩存
/**
* @author genialsir@163.com (GenialSir) on 2019/5/10
*/
public class RxImageLoader {
static RxImageLoader singleton;
private String mUrl;
private final RequestCreator requestCreator;
private RxImageLoader(Builder builder) {
requestCreator = new RequestCreator(builder.mContext);
}
public static RxImageLoader with(Context context) {
if (singleton == null) {
synchronized (RxImageLoader.class) {
if (singleton == null) {
singleton = new Builder(context).build();
}
}
}
return singleton;
}
public RxImageLoader load(String url) {
mUrl = url;
return singleton;
}
public void into(final ImageView imgView) {
//Concat等待訂閱你傳遞給它的每一個其餘Observable,直到上一個Observable完成。
Observable.concat(requestCreator.getMemoryCacheObservable(mUrl),
requestCreator.getDiskCacheObservable(mUrl),
requestCreator.getNetworkCacheObservable(mUrl))
// rx1寫法 若Image爲null,則依次執行disk、Network。
//.first(new Func1<Image, Boolean>() {
//
// @Override
// public Boolean call(Image image) {
// //若數據爲null,則往下執行。
// return image != null;
// }
// })
//rx2寫法,用於校驗數據處理條件。
.filter(new Predicate<Image>() {
@Override
public boolean test(Image image) throws Exception {
//若無效連接或者無效bitmap則跳過不執行onNext。
return !(TextUtils.isEmpty(image.getUrl()) && image.getBitmap() == null);
}
})
//指定concat執行完第一個知足條件的則不往下執行。
.firstElement()
.toObservable()
.subscribe(new Observer<Image>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Image image) {
imgView.setImageBitmap(image.getBitmap());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
//Consumer有返回Observable對象。
// .subscribe(new Consumer<Image>() {
// @Override
//public void accept(Image image) throws Exception {
// imgView.setImageBitmap(image.getBitmap());
// }
// });
}
private static class Builder {
private Context mContext;
private Builder(Context context) {
mContext = context;
}
private RxImageLoader build() {
return new RxImageLoader(this);
}
}
}
複製代碼
3,管理Image屬性的Model:網絡
public class Image {
public Image(String url, Bitmap bitmap) {
this.url = url;
this.bitmap = bitmap;
}
private String url;
private Bitmap bitmap;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
}
複製代碼
4,咱們圖片框架展現順序基於Memory,Disk,Network,先生成共有的抽象類:框架
public abstract class CacheObservable {
public Observable<Image> getImage(final String url) {
return Observable.create(new ObservableOnSubscribe<Image>() {
@Override
public void subscribe(ObservableEmitter<Image> emitter) throws Exception {
//訂閱沒有解除
if (!emitter.isDisposed()) {
Image image = getDataFromCache(url);
if (image == null) {
//爲RXJava2 OnNext不容許爲Null值,傳入則不往下執行,so 建立Image空值對象。
//參考ObservableCreate函數中OnNext。
emitter.onNext(new Image("", null));
} else {
emitter.onNext(image);
}
emitter.onComplete();
}
}
})
//I/O操做(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的Scheduler。
.subscribeOn(Schedulers.io())
//它指定的操做將在Android主線程運行。
.observeOn(AndroidSchedulers.mainThread());
}
public abstract Image getDataFromCache(String url);
public abstract void putDataToCache(Image image);
}
複製代碼
5,Network緩存管理類:ide
public class NetworkCacheObservable extends CacheObservable {
@Override
public Image getDataFromCache(String url) {
Bitmap bitmap = downloadImage(url);
if(bitmap != null){
return new Image(url, bitmap);
}
return null;
}
@Override
public void putDataToCache(Image image) {
}
private Bitmap downloadImage(String url){
Bitmap bitmap = null;
InputStream inputStream = null;
try {
URLConnection con = new URL(url).openConnection();
inputStream = con.getInputStream();
bitmap = BitmapFactory.decodeStream(inputStream);
}catch (IOException e){
e.printStackTrace();
}finally {
if(inputStream != null){
try {
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
return bitmap;
}
}
複製代碼
6,Disk緩存管理類:函數
public class DiskCacheObservable extends CacheObservable {
//DiskLruCache中對於圖片的最大緩存值.
private static final int maxSize = 30 * 1024 * 1024;
private Context mContext;
private DiskLruCache mDiskLruCache;
public DiskCacheObservable(Context context) {
mContext = context;
initDiskLruCache();
}
private void initDiskLruCache() {
try {
File cacheDir = DiskCacheUtil.getDiskCacheDir(mContext, "image_cache");
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
int versionCode = DiskCacheUtil.getAppVersionCode(mContext);
mDiskLruCache = DiskLruCache.open(cacheDir, versionCode, 1, maxSize);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Image getDataFromCache(String url) {
Bitmap bitmap = getDataFromDiskLruCache(url);
if (bitmap != null) {
return new Image(url, bitmap);
}
return null;
}
private Bitmap getDataFromDiskLruCache(String url) {
FileDescriptor fileDescriptor = null;
FileInputStream fileInputStream = null;
DiskLruCache.Snapshot snapshot = null;
try {
//生成圖片URL對應的key
String key = DiskCacheUtil.getMd5String(url);
//查找key對應的緩存
snapshot = mDiskLruCache.get(key);
if (snapshot != null) {
fileInputStream = (FileInputStream) snapshot.getInputStream(0);
fileDescriptor = fileInputStream.getFD();
}
//將緩存數據解析成Bitmap對象
Bitmap bitmap = null;
if (fileDescriptor != null) {
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
}
return bitmap;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileDescriptor == null && fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
}
}
}
return null;
}
@Override
public void putDataToCache(Image image) {
try {
//第一步:獲取將要緩存的圖片的對應惟一key值
String key = DiskCacheUtil.getMd5String(image.getUrl());
//第二步:獲取DiskLruCache的Editor
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
//第三步:從Editor中獲取OutputStream
OutputStream outputStream = editor.newOutputStream(0);
//第四步:下載網絡圖片且保存至DiskLruCache圖片緩存中
boolean isSuccessful = download(image.getUrl(), outputStream);
if (isSuccessful) {
editor.commit();
} else {
editor.abort();
}
mDiskLruCache.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean download(String downloadUrl, OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
final URL url = new URL(downloadUrl);
urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
out = new BufferedOutputStream(outputStream, 8 * 1024);
int buffer;
while ((buffer = in.read()) != -1) {
out.write(buffer);
}
//download successfully.
return true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
複製代碼
7 Memory緩存管理類:ui
public class MemoryCacheObservable extends CacheObservable {
//KB
private int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
private int cacheSize = maxMemory / 8;
private LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
};
@Override
public Image getDataFromCache(String url) {
Bitmap bitmap = mLruCache.get(url);
if (bitmap != null) {
return new Image(url, bitmap);
}
return null;
}
@Override
public void putDataToCache(Image image) {
if (image != null) {
mLruCache.put(image.getUrl(), image.getBitmap());
}
}
}
複製代碼
8 生成統一管理緩存類:this
public class RequestCreator {
private static final String TAG = "RequestCreator";
private MemoryCacheObservable memoryCacheObservable;
private DiskCacheObservable diskCacheObservable;
private NetworkCacheObservable networkCacheObservable;
public RequestCreator(Context context){
memoryCacheObservable = new MemoryCacheObservable();
diskCacheObservable = new DiskCacheObservable(context);
networkCacheObservable = new NetworkCacheObservable();
複製代碼
}
public Observable<Image> getMemoryCacheObservable(String url) {
Log.d(TAG, "getMemoryCacheObservable url is " + url);
return memoryCacheObservable.getImage(url)
.filter(new Predicate<Image>() {
@Override
public boolean test(Image image) throws Exception {
return !(TextUtils.isEmpty(image.getUrl()) && image.getBitmap() == null);
}
})
.doOnNext(new Consumer<Image>() {
@Override
public void accept(Image image) throws Exception {
Log.d(TAG,"getMemoryCacheObservable get data from memory" + image);
}
});
}
public Observable<Image> getDiskCacheObservable(String url) {
Log.d(TAG, "getDiskCacheObservable url is " + url);
return diskCacheObservable.getImage(url)
.filter(new Predicate<Image>() {
@Override
public boolean test(Image image) throws Exception {
return !(TextUtils.isEmpty(image.getUrl()) && image.getBitmap() == null);
}
})
.doOnNext(new Consumer<Image>() {
@Override
public void accept(Image image) throws Exception {
Log.d(TAG,"getDiskCacheObservable accept");
memoryCacheObservable.putDataToCache(image);
}
});
}
public Observable<Image> getNetworkCacheObservable(String url) {
Log.d(TAG, "getNetworkCacheObservable url is " + url);
return networkCacheObservable.getImage(url)
.filter(new Predicate<Image>() {
@Override
public boolean test(Image image) throws Exception {
return image != null;
}
})
.doOnNext(new Consumer<Image>() {
@Override
public void accept(Image image) throws Exception {
Log.d(TAG,"getNetworkCacheObservable accept.");
diskCacheObservable.putDataToCache(image);
memoryCacheObservable.putDataToCache(image);
}
});
}
}
複製代碼
至此,基於RxJava2簡易版的圖片緩存框架完成,如有問題請評論留言。如果感受對你有些幫助的話點個喜歡,多多益善,哈哈。