package org.succlz123.s1go.app.ui.picture; import com.facebook.binaryresource.BinaryResource; import com.facebook.binaryresource.FileBinaryResource; import com.facebook.cache.common.CacheKey; import com.facebook.common.executors.CallerThreadExecutor; import com.facebook.common.references.CloseableReference; import com.facebook.datasource.DataSource; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.imagepipeline.cache.DefaultCacheKeyFactory; import com.facebook.imagepipeline.core.ImagePipeline; import com.facebook.imagepipeline.core.ImagePipelineFactory; import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber; import com.facebook.imagepipeline.image.CloseableImage; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequestBuilder; import org.succlz123.s1go.app.utils.common.FileUtils; import android.graphics.Bitmap; import android.net.Uri; import android.os.Environment; import android.support.annotation.Nullable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import rx.Emitter; import rx.Observable; import rx.Subscriber; import rx.functions.Action1; import static android.os.Environment.DIRECTORY_PICTURES; /** * Created by succlz123 on 2016/11/28. */ public class PicDataSource implements PicContract.DataSource { @Override public Observable<Object> getBitmap(String url) { final Uri uri = Uri.parse(url); final ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri).build(); final ImagePipeline imagePipeline = Fresco.getImagePipeline(); final DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null); Observable<Bitmap> observable1 = Observable.fromEmitter(new Action1<Emitter<Bitmap>>() { @Override public void call(final Emitter<Bitmap> bitmapEmitter) { dataSource.subscribe(new BaseBitmapDataSubscriber() { @Override public void onNewResultImpl(@Nullable final Bitmap bitmap) { bitmapEmitter.onNext(bitmap); // dataSource.close(); bitmapEmitter.onCompleted(); } @Override public void onFailureImpl(DataSource dataSource) { bitmapEmitter.onError(null); } }, CallerThreadExecutor.getInstance()); } }, Emitter.BackpressureMode.BUFFER); Observable<String> observable2 = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(imageRequest, null); File file = getCachedImageOnDisk(cacheKey); if (file != null) { subscriber.onNext(file.toString()); subscriber.onCompleted(); } else { subscriber.onError(null); } } }); return Observable.merge(observable1, observable2); } @Override public Observable<Boolean> savePic(String url) { final Uri uri = Uri.parse(url); final ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri).build(); final ImagePipeline imagePipeline = Fresco.getImagePipeline(); File appDir = Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES); if (!appDir.exists()) { appDir.mkdir(); } String desc = String.valueOf(url.hashCode()) + url.length(); String fileName = desc + ".jpg"; final File newFile = new File(appDir, fileName); return Observable.fromEmitter(new Action1<Emitter<Boolean>>() { @Override public void call(final Emitter<Boolean> bitmapEmitter) { CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(imageRequest, null); File file = getCachedImageOnDisk(cacheKey); if (file != null && file.exists()) { bitmapEmitter.onNext(FileUtils.copyTo(file, newFile)); bitmapEmitter.onCompleted(); return; } DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null); dataSource.subscribe(new BaseBitmapDataSubscriber() { @Override public void onNewResultImpl(@Nullable final Bitmap bitmap) { if (bitmap != null) { try { FileOutputStream fos = new FileOutputStream(newFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); bitmapEmitter.onNext(false); } bitmapEmitter.onNext(true); } else { bitmapEmitter.onNext(false); } bitmapEmitter.onCompleted(); } @Override public void onFailureImpl(DataSource dataSource) { bitmapEmitter.onError(null); } }, CallerThreadExecutor.getInstance()); } }, Emitter.BackpressureMode.BUFFER); } public File getCachedImageOnDisk(CacheKey cacheKey) { File localFile = null; if (cacheKey != null) { if (ImagePipelineFactory.getInstance().getMainFileCache().hasKey(cacheKey)) { BinaryResource resource = ImagePipelineFactory.getInstance().getMainFileCache().getResource(cacheKey); localFile = ((FileBinaryResource) resource).getFile(); } else if (ImagePipelineFactory.getInstance().getSmallImageFileCache().hasKey(cacheKey)) { BinaryResource resource = ImagePipelineFactory.getInstance().getSmallImageFileCache().getResource(cacheKey); localFile = ((FileBinaryResource) resource).getFile(); } } return localFile; } }