-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Displaying Images with the Fresco Library
Fresco is a powerful library for displaying images in Android, supporting applications all the way back to GingerBread (API 9). It downloads and caches remote images in a memory efficient manner, using a special region of non-garbage collected memory on Android called ashmem
.
When working with Fresco, it's helpful to be familiar with the following terms:
- ImagePipeline - Responsible for getting you the image. It fetches from the network, a local file, a content provider, or a local resource. It keeps a cache of compressed images in local storage, and a second cache of decompressed images in memory.
- Drawee - Drawees deal with rendering images on screen and are made up of 3 parts.
- DraweeView - The view that shows the image. It extends from
ImageView
, but only for convenience (see the gotchas below for more info on this). Most of the time you'll be using aSimpleDraweeView
in your code. - DraweeHierarchy - Fresco provides a lot of customization. You can add a placeholderImage, a retryImage, a failureImage, a backgroundImage, etc. The hierarchy is what keeps track of all these drawables and when they should be shown.
- DraweeController - This is the class responsible for dealing with the image loader. Fresco allows you to customize the image loader if you don't want to use the provided
ImagePipeline
.
- DraweeView - The view that shows the image. It extends from
First, make sure to add the Fresco dependency in your app/build.gradle file:
dependencies {
implementation 'com.facebook.fresco:fresco:1.10.0'
}
Then, in your AndroidManifest.xml
make you have the Internet permission if you plan to fetch any images from the network:
<uses-permission android:name="android.permission.INTERNET"/>
Next, make sure to initialize Fresco. Fresco needs to be initialized before you call setContentView()
in any Activity
that uses Fresco
.
Fresco.initialize(context);
And then include it in your layout:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/sdvImage"
android:layout_width="130dp"
android:layout_height="130dp"
fresco:placeholderImage="@drawable/myPlaceholderImage" />
Note: If you want to use any Fresco defined properties, you'll need to add a custom namespace definition:
xmlns:fresco="http://schemas.android.com/apk/res-auto"
Finally, set the actual image URI:
Uri imageUri = Uri.parse("https://i.imgur.com/tGbaZCY.jpg");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.sdvImage);
draweeView.setImageURI(imageUri);
That's all you need to get started using Fresco, but Fresco can do much more than that. Below you can find a majority of the properties that Fresco supports.
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp"
android:layout_height="20dp"
fresco:fadeDuration="300"
fresco:actualImageScaleType="focusCrop"
fresco:placeholderImage="@color/wait_color"
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImage="@drawable/error"
fresco:failureImageScaleType="centerInside"
fresco:retryImage="@drawable/retrying"
fresco:retryImageScaleType="centerCrop"
fresco:progressBarImage="@drawable/progress_bar"
fresco:progressBarImageScaleType="centerInside"
fresco:progressBarAutoRotateInterval="1000"
fresco:backgroundImage="@color/blue"
fresco:overlayImage="@drawable/watermark"
fresco:pressedStateOverlayImage="@color/red"
fresco:roundAsCircle="false"
fresco:roundedCornerRadius="1dp"
fresco:roundTopLeft="true"
fresco:roundTopRight="false"
fresco:roundBottomLeft="false"
fresco:roundBottomRight="true"
fresco:roundWithOverlayColor="@color/corner_color"
fresco:roundingBorderWidth="2dp"
fresco:roundingBorderColor="@color/border_color" />
Note: DraweeView doesn't support specifying wrap_content
for the layout_width
or layout_height
attributes. This is to prevent situations where your placeholder image might be a different size than your actual image, forcing Android to do another layout pass once the actual image comes in.
There is only one case where DraweeView supports wrap_content
and this is for the helpful viewAspectRatio
property, allowing you to configure an aspect ratio.
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp"
android:layout_height="wrap_content"
fresco:viewAspectRatio="1.33" />
You can read more about Fresco's capabilities in the Fresco docs.
Getting the bitmap out of a SimpleDraweeView requires working with the ImagePipeline
instead of the DraweeView
itself. The code below shows how to get a bitmap out of the ImagePipeline
, which comes in useful when you want to share an image with another user.
ImagePipeline imagePipeline = Fresco.getImagePipeline();
ImageRequest imageRequest = ImageRequestBuilder
.newBuilderWithSource(imageUri)
.setRequestPriority(Priority.HIGH)
.setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)
.build();
DataSource<CloseableReference<CloseableImage>> dataSource =
imagePipeline.fetchDecodedImage(imageRequest, mContext);
try {
dataSource.subscribe(new BaseBitmapDataSubscriber() {
@Override
public void onNewResultImpl(@Nullable Bitmap bitmap) {
if (bitmap == null) {
Log.d(TAG, "Bitmap data source returned success, but bitmap null.");
return;
}
// The bitmap provided to this method is only guaranteed to be around
// for the lifespan of this method. The image pipeline frees the
// bitmap's memory after this method has completed.
//
// This is fine when passing the bitmap to a system process as
// Android automatically creates a copy.
//
// If you need to keep the bitmap around, look into using a
// BaseDataSubscriber instead of a BaseBitmapDataSubscriber.
}
@Override
public void onFailureImpl(DataSource dataSource) {
// No cleanup required here
}
}, CallerThreadExecutor.getInstance());
} finally {
if (dataSource != null) {
dataSource.close();
}
}
Make sure to add the following permissions to your AndroidManifest.xml
:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Note: The permissions model has changed starting in Marshmallow. If your targetSdkVersion
>= 23
and you are running on a Marshmallow (or later) device, you may need to enable runtime permissions. You can also read more about the runtime permissions changes here.
To share an image from Fresco, you first need to get the bitmap from the ImagePipeline
. Then you can use the following code to save the bitmap to the Media image store and pass the path into a share intent.
public void shareBitmap(Bitmap bitmap) {
String path = MediaStore.Images.Media.insertImage(mContext.getContentResolver(),
bitmap, "Image Description", null);
Uri bmpUri = Uri.parse(path);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
shareIntent.setType("image/*");
mContext.startActivity(Intent.createChooser(shareIntent, "Share Image"));
}
See the guide on sharing if you want to read more about the different sharing options.
Make sure you review the list of gotchas in the Fresco documentation. The most notable one is to avoid ImageView
methods and properties when dealing with a DraweeView
(even though DraweeView
extends ImageView
).
- Don't call ImageView methods
setImageBitmap
,setImageDrawable
, etc as this will wipe out theDraweeHierarchy
- Don't set
ImageView
properties likescaleType
,src
, etc. Instead use the DraweeView counterparts for these properties.
- http://frescolib.org/index.html
- https://code.facebook.com/posts/366199913563917/introducing-fresco-a-new-image-library-for-android/
- https://github.com/facebook/fresco
- http://www.nurne.com/2012/07/android-how-to-attach-image-file-from.html
- http://www.birdcommunication.in/attach-image-android.php
Created by CodePath with much help from the community. Contributed content licensed under cc-wiki with attribution required. You are free to remix and reuse, as long as you attribute and use a similar license.
Finding these guides helpful?
We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.
Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.