Fresco 是 Facebook 推出的Android 高性能图片加载框架,专为解决 Android 图片加载的痛点设计:自动处理内存 / 磁盘缓存、支持超大图渐进式加载、完美适配 RecyclerView 列表复用、自动释放内存(Activity 销毁时无需手动处理),还支持 GIF/WEBP 动图、图片裁剪 / 圆角等特效,是中大型 Android 项目的主流图片加载框架之一。
下面从依赖引入、基础配置、核心用法、高频场景、高级定制、避坑点 全维度讲解,适配Gradle Kotlin DSL(build.gradle.kts) 和 Kotlin 语法,代码可直接复制使用,覆盖 99% 的开发场景。
一、核心优势(为什么选 Fresco)
对比 Glide/Picasso,Fresco 的核心优势集中在内存优化 和大尺寸图片处理:
- 内存占用极低 :图片默认存储在Ashmem(匿名共享内存),而非 Java 堆,避免 OOM(内存溢出),尤其适合加载高清图 / 长图;
- 自动缓存策略:三级缓存(内存 / 磁盘 / 网络),可自定义缓存规则,支持断点续传;
- 动图原生支持:无需额外依赖,直接加载 GIF/WEBP 动图,支持暂停 / 播放;
- 渐进式加载 :超大图(如长图、高清海报)可像网页一样从模糊到清晰渐进加载,提升用户体验;
- 生命周期绑定:与 Activity/Fragment 生命周期自动绑定,页面销毁时自动停止加载、释放资源,无需手动处理;
- 丰富的图片特效:内置圆角、圆形、裁剪、淡入淡出等效果,无需自定义 ImageView。
适用场景 :需要加载高清图 / 长图、动图,或对内存优化要求高的项目(如电商、社交、资讯 APP);轻量场景:若仅加载普通小图,Glide 更轻量,可根据项目需求选择。
二、前置步骤:依赖引入 + 权限配置(必做)
2.1 添加 Fresco 核心依赖(app/build.gradle.kts)
Fresco 的依赖支持按需引入 (核心包 + 扩展包),基础使用仅需核心包,动图 / 网络扩展可按需添加。最新稳定版为 2.7.0,适配 Android 5.0+(API 21+),低版本需兼容配置(文末补充)。
打开 App 模块的build.gradle.kts,在dependencies中添加依赖,同步后即可使用:
kotlin
dependencies {
// 其他原有依赖(kotlin-stdlib、core-ktx等)保留
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
implementation("androidx.core:core-ktx:1.12.0")
// 核心:Fresco基础包(必须加,支持本地/网络图片、缓存、基础特效)
implementation("com.facebook.fresco:fresco:2.7.0")
// 按需添加扩展包(根据业务需求选择,无需全部添加)
implementation("com.facebook.fresco:animated-gif:2.7.0") // 支持GIF动图
implementation("com.facebook.fresco:animated-webp:2.7.0") // 支持WEBP动图
implementation("com.facebook.fresco:webpsupport:2.7.0") // 支持静态WEBP
implementation("com.facebook.fresco:okhttp3-imagepipeline:2.7.0") // 用OkHttp3作为网络层(推荐,替代默认HttpURLConnection)
}
建议添加
okhttp3-imagepipeline:Fresco 默认网络层是HttpURLConnection,替换为 OkHttp3 后支持HTTPS、拦截器、超时配置,更适配实际开发。
2.2 配置网络权限(AndroidManifest.xml)
加载网络图片 / 动图 必须添加网络权限,Android 9.0+(API 28)若加载http链接图片,需开启明文网络支持:
xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="你的项目包名">
<!-- 必加:网络权限(加载网络图片) -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 可选:读写外部存储(加载本地图片/缓存到外部) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
<!-- Android 9.0+ 加载http链接图片需加:开启明文网络支持 -->
<uses-library android:name="org.apache.http.legacy" android:required="false" />
<meta-data
android:name="android.webkit.WebSettings.ALLOW_UNIVERSAL_ACCESS_FROM_FILE_URLS"
android:value="true" />
<!-- 或直接在res/xml创建network_security_config.xml,配置更灵活(推荐) -->
<!-- 你的Activity配置 -->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Android 10+ 存储适配 :若需将缓存放在外部存储,需在application中添加android:preserveLegacyExternalStorage="true",或使用 Scoped Storage(作用域存储)。
2.3 初始化 Fresco(全局唯一,Application 中执行)
Fresco 必须全局初始化一次 ,建议放在自定义 Application 类 的onCreate中,这是 Android 开发的最佳实践,避免多次初始化导致资源泄漏。
步骤 1:创建自定义 Application 类
kotlin
import android.app.Application
import com.facebook.drawee.backends.pipeline.Fresco
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// 基础初始化:默认配置(满足90%的基础场景)
Fresco.initialize(this)
// 进阶:自定义配置(如OkHttp3网络层、缓存大小、超时时间,文末高级部分讲解)
// Fresco.initialize(this, getFrescoConfig())
}
}
步骤 2:在 AndroidManifest.xml 中注册 Application
xml
<application
android:name=".MyApp" <!-- 对应自定义Application类 -->
...>
<!-- 其他配置 -->
</application>
注意:初始化必须用Application 上下文,不能用 Activity 上下文,否则会导致内存泄漏。
三、核心布局控件:SimpleDraweeView(替代 ImageView)
Fresco不使用原生 ImageView ,而是提供专属的SimpleDraweeView控件,所有图片加载 / 特效都通过该控件实现,它继承自ImageView,可直接在布局中使用,支持 XML 属性配置占位图、圆角、宽高比等。
3.1 布局中使用 SimpleDraweeView(核心)
在layout/xxx.xml中添加SimpleDraweeView,替代原有ImageView,基础属性说明:
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto" <!-- 必加:Fresco命名空间 -->
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<!-- 基础使用:加载网络图片,配置占位图、圆角 -->
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/sdv_avatar"
android:layout_width="100dp" <!-- 支持固定宽高/match_parent/wrap_content -->
android:layout_height="100dp"
fresco:fadeDuration="300" <!-- 淡入淡出动画时长(ms),默认300 -->
fresco:placeholderImage="@mipmap/ic_placeholder" <!-- 加载中占位图 -->
fresco:placeholderImageScaleType="centerCrop" <!-- 占位图缩放类型 -->
fresco:errorImage="@mipmap/ic_error" <!-- 加载失败占位图 -->
fresco:retryImage="@mipmap/ic_retry" <!-- 加载重试占位图 -->
fresco:roundAsCircle="true" <!-- 是否圆形显示(头像专用,与roundRadius二选一) -->
<!-- fresco:roundRadius="10dp" --> <!-- 圆角半径(非圆形时使用) -->
fresco:roundWithOverlayColor="@color/white" <!-- 圆角边缘叠加色(解决透明图圆角锯齿) -->
fresco:viewAspectRatio="1:1" <!-- 宽高比(如16:9,设置后可省略width/height其中一个) -->
/>
<!-- 加载长图/超大图:支持渐进式加载 -->
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/sdv_long_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
fresco:viewAspectRatio="3:4"
fresco:placeholderImage="@mipmap/ic_placeholder"
fresco:progressBarImage="@mipmap/ic_progress" <!-- 进度条占位图(渐进式加载) -->
fresco:progressBarImageScaleType="centerInside"
/>
<!-- 加载GIF动图:无需额外配置,核心包+animated-gif扩展即可 -->
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/sdv_gif"
android:layout_width="200dp"
android:layout_height="200dp"
fresco:placeholderImage="@mipmap/ic_placeholder"
/>
</LinearLayout>
核心 XML 属性说明(常用)
| 属性名 | 作用 | 常用值 |
|---|---|---|
fresco:placeholderImage |
加载中占位图 | 本地 mipmap/drawable 资源 |
fresco:errorImage |
加载失败占位图 | 本地资源 |
fresco:roundAsCircle |
是否圆形显示 | true/false(头像用) |
fresco:roundRadius |
圆角半径 | 如10dp |
fresco:viewAspectRatio |
宽高比 | 如16:9、1:1 |
fresco:fadeDuration |
淡入动画时长 | 如300(ms) |
fresco:progressBarImage |
渐进式加载进度条 | 本地资源 |
fresco:roundWithOverlayColor |
圆角边缘色 | 如@color/white(解决透明图锯齿) |
注意:
SimpleDraweeView的wrap_content需要配合viewAspectRatio使用,否则图片可能显示异常;固定宽高可直接使用,无需宽高比。
四、核心用法:加载图片(Kotlin)
Fresco 加载图片的核心是 **ImageRequest(图片请求)** + DraweeController(控制器) ,通过SimpleDraweeView.setController()绑定加载配置,支持网络图片、本地图片、Assets 图片、Drawable 图片等多种数据源,语法统一。
先定义测试地址(方便复制测试)
kotlin
// 测试1:网络图片(jpg)
val netImageUrl = "https://img1.baidu.com/it/u=123456,789012&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"
// 测试2:网络GIF动图
val netGifUrl = "https://img1.baidu.com/it/u=345678,901234&fm=253&fmt=auto&app=138&f=GIF?w=300&h=300"
// 测试3:本地图片(sdcard)
val localImagePath = "file:///sdcard/Pictures/test.jpg"
// 测试4:Assets图片(assets/test.png)
val assetsImageUrl = "asset:///test.png"
// 测试5:Drawable图片(R.drawable.test)
val drawableResId = R.drawable.test
4.1 基础加载:一行代码加载网络图片(默认配置)
适合无需自定义配置的简单场景,用Fresco.newDraweeControllerBuilder()快速构建控制器:
kotlin
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
class MainActivity : AppCompatActivity() {
private lateinit var sdvAvatar: SimpleDraweeView
private lateinit var sdvGif: SimpleDraweeView
private lateinit var sdvLongImg: SimpleDraweeView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 注意:Fresco初始化后,可直接设置布局,无需额外操作
setContentView(R.layout.activity_main)
// 绑定控件
sdvAvatar = findViewById(R.id.sdv_avatar)
sdvGif = findViewById(R.id.sdv_gif)
sdvLongImg = findViewById(R.id.sdv_long_img)
// 用法1:加载普通网络图片(基础版,一行代码)
sdvAvatar.setImageURI(netImageUrl) // 极简用法,默认配置(推荐基础场景)
// 用法2:加载GIF动图(无需额外配置,添加animated-gif扩展即可)
sdvGif.setImageURI(netGifUrl)
}
}
极简用法
setImageURI(uri):底层自动构建默认的ImageRequest和DraweeController,满足 90% 的基础加载场景,推荐优先使用。
4.2 进阶加载:自定义 ImageRequest(渐进式 / 超时 / 缓存)
适合需要自定义加载规则 的场景(如超大图渐进式加载、设置超时时间、禁用缓存、强制刷新),通过ImageRequestBuilder构建请求,灵活配置参数:
kotlin
// 用法3:加载超大图/长图 → 开启渐进式加载(核心)
val longImageRequest = ImageRequestBuilder
.newBuilderWithSource(Uri.parse(netImageUrl)) // 绑定图片地址(Uri格式)
.setProgressiveRenderingEnabled(true) // 开启渐进式加载(从模糊到清晰)
.setRequestPriority(ImageRequest.Priority.HIGH) // 设置加载优先级(HIGH/LOW/NORMAL)
.setCacheChoice(ImageRequest.CacheChoice.DEFAULT) // 缓存策略(默认/仅内存/仅磁盘)
.setNetworkFetchTimeout(5000) // 网络超时时间(ms),默认5000
.build()
// 构建DraweeController,绑定请求
val longImgController = Fresco.newDraweeControllerBuilder()
.setImageRequest(longImageRequest)
.setAutoPlayAnimations(true) // 自动播放动图(默认true)
.setOldController(sdvLongImg.controller) // 重用旧控制器(RecyclerView列表复用必备,防止闪烁)
.build()
// 绑定到控件
sdvLongImg.controller = longImgController
核心 ImageRequestBuilder 配置(常用)
| 方法 | 作用 | 常用值 |
|---|---|---|
setProgressiveRenderingEnabled(true) |
开启渐进式加载 | 超大图 / 长图必开 |
setRequestPriority(...) |
加载优先级 | HIGH(首屏图)/LOW(非首屏) |
setNetworkFetchTimeout(ms) |
网络超时 | 如5000(ms) |
setCacheChoice(...) |
缓存策略 | DEFAULT(默认)/NO_CACHE(禁用缓存) |
setResizeOptions(ResizeOptions(w, h)) |
图片缩放 | 如ResizeOptions(200,200)(像素),减少内存占用 |
setLocalThumbnailPreviewsEnabled(true) |
开启本地缩略图预览 | 加载本地大图时提速 |
4.3 加载不同数据源(本地 / Assets/Drawable)
Fresco 通过不同的 Uri 协议区分数据源,语法统一,仅需修改 Uri 格式,无需更改加载逻辑:
kotlin
import android.net.Uri
import com.facebook.drawee.drawable.ScalingUtils
// 1. 加载本地SDCard图片(协议:file:///)
val localUri = Uri.parse("file:///sdcard/Pictures/test.jpg")
sdvAvatar.setImageURI(localUri)
// 2. 加载Assets目录图片(协议:asset:///,注意3个/)
val assetsUri = Uri.parse("asset:///test.png") // 对应assets/test.png
sdvAvatar.setImageURI(assetsUri)
// 3. 加载Drawable/mipmap资源(需通过UriUtil构建)
import com.facebook.common.util.UriUtil
val drawableUri = Uri.parse(UriUtil.LOCAL_RESOURCE_SCHEME + ":" + R.drawable.test)
sdvAvatar.setImageURI(drawableUri)
// 4. 加载ContentProvider图片(如相册图片,协议:content://)
val contentUri = Uri.parse("content://media/external/images/media/12345")
sdvAvatar.setImageURI(contentUri)
4.4 动图专属操作(暂停 / 播放 / 循环次数)
加载 GIF/WEBP 动图后,可通过Animatable接口控制播放 / 暂停,支持设置循环次数:
kotlin
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.imagepipeline.image.ImageInfo
import com.facebook.drawee.controller.ControllerListener
// 步骤1:构建控制器时,添加监听器(获取动图Animatable对象)
val gifController = Fresco.newDraweeControllerBuilder()
.setUri(netGifUrl)
.setAutoPlayAnimations(false) // 关闭自动播放,手动控制
.setControllerListener(object : BaseControllerListener<ImageInfo>() {
// 图片加载完成回调
override fun onFinalImageSet(
id: String?,
imageInfo: ImageInfo?,
animatable: com.facebook.drawee.controller.Animatable?
) {
super.onFinalImageSet(id, imageInfo, animatable)
// 保存Animatable对象,用于手动控制
animatable?.let {
mGifAnimatable = it
// 设置动图循环次数(-1为无限循环,默认)
(it as? com.facebook.imagepipeline.animated.base.AnimatedDrawable)?.setLoopCount(3)
}
}
})
.build()
sdvGif.controller = gifController
// 步骤2:手动控制动图(按钮点击事件)
private var mGifAnimatable: com.facebook.drawee.controller.Animatable? = null
// 播放动图
btnPlay.setOnClickListener { mGifAnimatable?.start() }
// 暂停动图
btnPause.setOnClickListener { mGifAnimatable?.stop() }
五、高频场景:RecyclerView 列表图片加载(必懂)
RecyclerView 列表中使用 Fresco 的核心是重用旧控制器,防止图片闪烁、重复加载,这是 Fresco 针对列表复用的专属优化,只需一行代码即可实现:
kotlin
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.facebook.drawee.view.SimpleDraweeView
class ImageAdapter(private val imageList: List<String>) : RecyclerView.Adapter<ImageAdapter.ViewHolder>() {
inner class ViewHolder(itemView: android.view.View) : RecyclerView.ViewHolder(itemView) {
val sdvItem: SimpleDraweeView = itemView.findViewById(R.id.sdv_item)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_image, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val imageUrl = imageList[position]
// 核心:重用旧控制器(setOldController),防止列表滑动时图片闪烁/重复加载
val controller = Fresco.newDraweeControllerBuilder()
.setUri(imageUrl)
.setOldController(holder.sdvItem.controller) // 关键代码,必须加
.build()
holder.sdvItem.controller = controller
}
override fun getItemCount() = imageList.size
}
核心原理:Fresco 会复用旧的加载控制器,避免列表项复用后重新发起网络请求,同时自动取消滑出屏幕的图片加载,节省流量和内存。
六、高级定制:自定义 Fresco 配置(OkHttp3 / 缓存 / 超时)
基础初始化Fresco.initialize(this)使用默认配置,实际开发中常需要替换网络层为 OkHttp3、自定义缓存大小、设置网络拦截器 ,通过ImagePipelineConfig构建自定义配置,步骤如下:
6.1 自定义 OkHttp3 网络层(推荐)
替换 Fresco 默认的HttpURLConnection为 OkHttp3,支持 HTTPS、拦截器(如添加请求头、日志拦截)、超时配置:
kotlin
import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory
import com.facebook.imagepipeline.core.ImagePipelineConfig
import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit
// 在自定义Application中构建自定义配置
private fun getFrescoConfig(): ImagePipelineConfig {
// 1. 构建OkHttpClient,自定义配置
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS) // 连接超时
.readTimeout(10, TimeUnit.SECONDS) // 读取超时
.writeTimeout(10, TimeUnit.SECONDS) // 写入超时
.addInterceptor(MyLogInterceptor()) // 添加自定义日志拦截器
.addInterceptor(MyHeaderInterceptor()) // 添加请求头拦截器(如Token)
.build()
// 2. 基于OkHttp3构建ImagePipelineConfig
return OkHttpImagePipelineConfigFactory
.newBuilder(this, okHttpClient)
.setBitmapMemoryCacheParamsSupplier {
// 3. 自定义内存缓存大小(可选)
com.facebook.imagepipeline.cache.BitmapMemoryCacheParams(
"myBitmapCache", // 缓存名称
Int.MAX_VALUE, // 最大缓存条目
100 * 1024 * 1024, // 最大缓存大小(100MB)
Int.MAX_VALUE,
Int.MAX_VALUE
)
}
.setMainDiskCacheConfig(
// 4. 自定义磁盘缓存配置(可选)
com.facebook.imagepipeline.cache.DiskCacheConfig.newBuilder(this)
.setBaseDirectoryPath(getExternalFilesDir("fresco_cache")) // 缓存路径
.setBaseDirectoryName("image_cache")
.setMaxCacheSize(500 * 1024 * 1024) // 磁盘最大缓存(500MB)
.build()
)
.setDownsampleEnabled(true) // 开启图片降采样(自动缩放,减少内存)
.build()
}
// 替换初始化代码
Fresco.initialize(this, getFrescoConfig())
6.2 常用高级配置说明
- 内存缓存 :默认按设备内存自动分配,自定义时建议设置为50-200MB;
- 磁盘缓存 :建议放在 App 私有目录(
getExternalFilesDir),无需存储权限,App 卸载时自动删除; - 降采样(Downsample) :开启后 Fresco 会根据
SimpleDraweeView的尺寸自动缩放图片,避免加载原图导致内存浪费; - 拦截器 :通过 OkHttp3 的拦截器可统一添加Token、User-Agent等请求头,或添加日志拦截器调试网络请求。
七、Fresco 核心类关系(快速理解)
为了避免混淆,简单梳理 Fresco 的核心类职责,帮助理解整体流程:
- Fresco:全局入口类,负责初始化、获取全局配置;
- SimpleDraweeView:图片展示控件,替代 ImageView,处理布局和特效;
- ImageRequest:图片请求类,封装图片地址、加载规则、超时、缓存等配置;
- DraweeController:加载控制器,绑定 ImageRequest 和 SimpleDraweeView,控制加载 / 暂停 / 复用;
- ImagePipeline:核心加载引擎,处理三级缓存、网络请求、图片解码、内存管理;
- Animatable:动图控制接口,实现 GIF/WEBP 的播放 / 暂停。
核心流程 :Fresco初始化 → 构建ImageRequest → 构建DraweeController绑定请求 → SimpleDraweeView设置控制器 → ImagePipeline处理加载 / 缓存 → 控件展示图片。
八、Kotlin 专属避坑点(Fresco 2.7.0)
Fresco 在 Android Kotlin 中使用的坑主要集中在控件使用、初始化、生命周期、内存优化,踩中后会出现图片不显示、OOM、内存泄漏等问题,务必注意:
1. 禁止使用原生 ImageView 加载
Fresco 的图片加载逻辑与SimpleDraweeView深度绑定,用 ImageView 无法加载 ,且会报空指针,必须使用com.facebook.drawee.view.SimpleDraweeView。
2. 必须全局初始化一次,且用 Application 上下文
- 初始化必须放在Application 的 onCreate中,不能在 Activity/Fragment 中初始化,否则会多次初始化导致资源冲突;
- 初始化参数必须是Application 上下文 (
this),不能用 Activity 上下文,否则会导致 Activity 无法被 GC 回收,引发内存泄漏。
3. RecyclerView 列表必须重用旧控制器
列表中加载图片若未调用setOldController(holder.sdvItem.controller),会出现图片闪烁、重复加载、滑出屏幕后继续加载的问题,这是 Fresco 列表使用的核心禁忌。
4. 避免设置 SimpleDraweeView 的 src 属性
原生 ImageView 的setImageResource/setImageBitmap对SimpleDraweeView无效,且会覆盖 Fresco 的加载逻辑,必须用setImageURI()或setController()设置图片。
5. 动图播放需注意内存释放
GIF/WEBP 动图会占用较多内存,页面销毁时需手动暂停动图,避免内存泄漏:
kotlin
override fun onDestroy() {
super.onDestroy()
mGifAnimatable?.stop() // 暂停动图
mGifAnimatable = null // 置空引用
}
6. Android 10+ 存储权限适配
加载本地 SDCard 图片时,Android 10+(API 29)默认开启Scoped Storage ,直接访问file:///sdcard会报权限错误,建议:
- 加载相册图片使用ContentProvider (
content://协议); - 自定义缓存路径使用 App 私有目录(
getExternalFilesDir),无需存储权限。
7. 混淆配置(Release 版必加)
若项目 Release 版开启混淆(isMinifyEnabled = true),必须在proguard-rules.pro中添加 Fresco 的混淆规则,否则会出现类找不到、图片加载失败:
proguard
# Fresco 基础混淆规则
-keep class com.facebook.** { *; }
-keep interface com.facebook.** { *; }
-keep enum com.facebook.** { *; }
-keep class com.facebook.imagepipeline.** { *; }
-keep class com.facebook.drawee.** { *; }
-dontwarn com.facebook.**
-dontwarn okio.**
# 若使用OkHttp3网络层
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
九、常见问题排查(图片不显示 / 加载失败)
按步骤操作后若图片不显示,按以下顺序排查,99% 的问题都能解决:
- 检查 Fresco 是否初始化 :确认自定义 Application 已注册,且
Fresco.initialize(this)已执行; - 检查网络权限 :加载网络图片必须添加
<uses-permission android:name="android.permission.INTERNET" />; - 检查 Uri 格式 :不同数据源的 Uri 协议是否正确(如 Assets 是
asset:///,3 个 /); - 检查依赖是否完整 :加载动图需添加
animated-gif/animated-webp扩展包; - 检查 SimpleDraweeView 属性 :是否正确设置
layout_width/layout_height,wrap_content是否配合viewAspectRatio; - 检查网络链接 :是否是
https链接(Android 9.0+ 默认禁止 http),或是否开启明文网络支持; - 检查日志 :查看 Logcat 的
Fresco/ImagePipeline相关日志,定位具体错误(如权限、网络超时、图片地址无效); - 清理缓存 :Fresco 有默认缓存,可通过
Fresco.getImagePipeline().clearCaches()清理缓存后重新测试; - 检查混淆规则:Release 版需添加 Fresco 的混淆规则,否则会解析失败。
十、与 Glide 的对比(如何选择)
Fresco 和 Glide 都是 Android 主流图片加载框架,各有优势,根据项目需求选择即可:
| 特性 | Fresco | Glide |
|---|---|---|
| 内存优化 | 极致(Ashmem 存储,非 Java 堆) | 优秀(内存缓存,自动回收) |
| 大尺寸图片 | 支持渐进式加载,体验极佳 | 支持加载,但无原生渐进式 |
| 动图支持 | 原生支持 GIF/WEBP,可手动控制 | 需添加glide-gif-drawable扩展 |
| 控件依赖 | 必须使用 SimpleDraweeView | 支持原生 ImageView,无控件依赖 |
| 上手难度 | 稍高(配置多,控件专属) | 极低(一行代码加载,API 简洁) |
| 体积 | 稍大(核心包≈2MB,全扩展≈5MB) | 轻量(核心包≈1.5MB) |
| 生态 | 稳定,无频繁更新 | 活跃,持续更新,适配最新 Android 版本 |
选择建议:
- 选Fresco:项目需要加载高清图 / 长图、动图,或对内存优化要求极高(如电商、社交 APP);
- 选Glide:轻量项目、快速开发,或习惯使用原生 ImageView,对大图片处理无特殊要求。
十一、总结(核心关键点)
- 核心步骤:添加依赖 → 配置权限 → Application 中初始化 Fresco → 布局使用 SimpleDraweeView → 代码中 setImageURI/setController 加载图片;
- 核心控件 :
SimpleDraweeView是 Fresco 的核心,替代 ImageView,支持 XML 配置圆角 / 圆形 / 占位图; - 核心用法 :极简加载用
setImageURI(uri),自定义配置用ImageRequest+DraweeController; - 列表优化 :RecyclerView 中必须调用
setOldController()重用旧控制器,防止图片闪烁; - 高级定制 :通过
ImagePipelineConfig替换 OkHttp3 网络层、自定义缓存大小、添加拦截器; - 避坑核心:全局初始化一次、用 Application 上下文、不设置 src 属性、动图页面销毁时暂停;
- 动图支持 :添加
animated-gif/animated-webp扩展包,通过Animatable接口控制播放 / 暂停。