我试图在我的Android应用中用Fresco替换Picasso。但是我不确定如何使用Fresco简单地加载位图。
毕加索我会做以下事情。
Bitmap poster = Picasso.with(getActivity())
.load(url)
.resize(Utils.convertDpToPixel(WIDTH,HEIGHT))
.centerCrop()
.get();
我一直无法弄清楚如何使用这个Fresco创建一个Bitmap。有任何想法吗?
答案 0 :(得分:20)
正如弗雷斯科所说:
如果您对管道的请求是针对解码图像(Android位图),您可以利用我们更容易使用的BaseBitmapDataSubscriber:
dataSource.subscribe(new BaseBitmapDataSubscriber() {
@Override
public void onNewResultImpl(@Nullable Bitmap bitmap) {
// You can use the bitmap in only limited ways
// No need to do any cleanup.
}
@Override
public void onFailureImpl(DataSource dataSource) {
// No cleanup required here.
}
},
executor);
您不能将位图分配给不在onNewResultImpl方法范围内的任何变量。
http://frescolib.org/docs/datasources-datasubscribers.html#_
我的代码:
public void setDataSubscriber(Context context, Uri uri, int width, int height){
DataSubscriber dataSubscriber = new BaseDataSubscriber<CloseableReference<CloseableBitmap>>() {
@Override
public void onNewResultImpl(
DataSource<CloseableReference<CloseableBitmap>> dataSource) {
if (!dataSource.isFinished()) {
return;
}
CloseableReference<CloseableBitmap> imageReference = dataSource.getResult();
if (imageReference != null) {
final CloseableReference<CloseableBitmap> closeableReference = imageReference.clone();
try {
CloseableBitmap closeableBitmap = closeableReference.get();
Bitmap bitmap = closeableBitmap.getUnderlyingBitmap();
if(bitmap != null && !bitmap.isRecycled()) {
//you can use bitmap here
}
} finally {
imageReference.close();
closeableReference.close();
}
}
}
@Override
public void onFailureImpl(DataSource dataSource) {
Throwable throwable = dataSource.getFailureCause();
// handle failure
}
};
getBitmap(context, uri, width, height, dataSubscriber);
}
/**
*
* @param context
* @param uri
* @param width
* @param height
* @param dataSubscriber
*/
public void getBitmap(Context context, Uri uri, int width, int height, DataSubscriber dataSubscriber){
ImagePipeline imagePipeline = Fresco.getImagePipeline();
ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);
if(width > 0 && height > 0){
builder.setResizeOptions(new ResizeOptions(width, height));
}
ImageRequest request = builder.build();
DataSource<CloseableReference<CloseableImage>>
dataSource = imagePipeline.fetchDecodedImage(request, context);
dataSource.subscribe(dataSubscriber, UiThreadExecutorService.getInstance());
}
答案 1 :(得分:2)
您可以直接使用Fresco的图像管道:
http://frescolib.org/docs/using-image-pipeline.html
虽然如果你不介意我的问题 - 这里的动机是什么?你为什么需要Bitmap?
答案 2 :(得分:2)
您可以直接使用Fresco的CacheKey:
public class DownloadVideoThumbnail extends AsyncTask<String, Void, Bitmap> {
private ImageView bmImage;
private Bitmap bitmapVideo;
private Context context;
public DownloadVideoThumbnail(Context context, ImageView bmImage) {
this.bmImage = (ImageView) bmImage;
this.context = context;
}
protected Bitmap doInBackground(String... urls) {
String urlStr = urls[0];
if (readFromCacheSync(urlStr) == null) {
try {
//Your method call here
bitmapVideo = retriveVideoFrameFromVideo(urlStr);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
} else {
bitmapVideo = readFromCacheSync(urlStr);
}
return null;
}
protected void onPostExecute(Bitmap result) {
if (bitmapVideo != null) {
//Load your bitmap here
bmImage.setImageBitmap(bitmapVideo);
bmImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
}
public void cacheBitmap(Bitmap bitmap, String url) {
try {
CacheKey cacheKey = new SimpleCacheKey(url);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
final byte[] byteArray = stream.toByteArray();
Fresco.getImagePipelineFactory().getMainFileCache().insert(cacheKey, new WriterCallback() {
@Override
public void write(OutputStream outputStream) throws IOException {
outputStream.write(byteArray);
}
});
} catch (IOException cacheWriteException) {
}
}
public static Bitmap readFromCacheSync(String imageUrl) {
CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(ImageRequest.fromUri(imageUrl), null);
StagingArea stagingArea = StagingArea.getInstance();
EncodedImage encodedImage = stagingArea.get(cacheKey);
if (encodedImage != null) {
return BitmapFactory.decodeStream(encodedImage.getInputStream());
}
try {
return BitmapFactory.decodeStream(readFromDiskCache(cacheKey));
} catch (Exception e) {
return null;
}
}
private static InputStream readFromDiskCache(final CacheKey key) throws IOException {
try {
FileCache fileCache = ImagePipelineFactory.getInstance().getMainFileCache();
final BinaryResource diskCacheResource = fileCache.getResource(key);
if (diskCacheResource == null) {
FLog.v(TAG, "Disk cache miss for %s", key.toString());
return null;
}
PooledByteBuffer byteBuffer;
final InputStream is = diskCacheResource.openStream();
FLog.v(TAG, "Successful read from disk cache for %s", key.toString());
return is;
} catch (IOException ioe) {
return null;
}
}
public Bitmap retriveVideoFrameFromVideo(String videoPath) throws Throwable {
Bitmap bitmap = null;
MediaMetadataRetriever mediaMetadataRetriever = null;
try {
mediaMetadataRetriever = new MediaMetadataRetriever();
if (Build.VERSION.SDK_INT >= 14)
mediaMetadataRetriever.setDataSource(videoPath, new HashMap<String, String>());
else
mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime();
if (bitmap != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
cacheBitmap(bitmap, videoPath);
}
} catch (Exception e) {
e.printStackTrace();
throw new Throwable(
"Exception in retriveVideoFrameFromVideo(String videoPath)"
+ e.getMessage());
} finally {
if (mediaMetadataRetriever != null) {
mediaMetadataRetriever.release();
}
}
return bitmap;
}
}
答案 3 :(得分:0)
从this开始,我创建了一个快速实现,该实现使用Kotlin扩展和RxJava从int
中获取ClosableBitmap
:
ImageRequest
由于合同规定,一旦使用了位图,就必须关闭引用,因此我创建了这个util函数:
fun ImageRequest.getBitmap(context: Context): Maybe<CloseableReference<CloseableBitmap>> {
val dataSource = Fresco.getImagePipeline().fetchDecodedImage(this, context)
return Maybe.create { emitter ->
dataSource.subscribe(
object : BaseDataSubscriber<CloseableReference<CloseableImage>>() {
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
emitter.onComplete()
}
override fun onNewResultImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
if (!dataSource.isFinished) {
return
}
dataSource.result
?.takeIf { it.get() is CloseableBitmap }
?.let {
@Suppress("UNCHECKED_CAST")
emitter.onSuccess(it as CloseableReference<CloseableBitmap>)
}
emitter.onComplete()
}
},
DefaultExecutorSupplier(1).forBackgroundTasks()
)
}
}
答案 4 :(得分:0)
我使用Kotlin的协程找到了这种解决方案:
suspend fun getBitmapFromUri(imageUri: Uri): Bitmap = withContext(Dispatchers.Default) {
val imageRequest = ImageRequestBuilder.newBuilderWithSource(imageUri).build()
val dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, this)
val result = DataSources.waitForFinalResult(dataSource) as CloseableReference<CloseableBitmap>
val bitmap = result.get().underlyingBitmap
CloseableReference.closeSafely(result)
dataSource.close()
return@withContext bitmap
}