Fresco2.X 框架完整使用详解(Android Kotlin)

Fresco 是 Facebook 推出的Android 高性能图片加载框架,专为解决 Android 图片加载的痛点设计:自动处理内存 / 磁盘缓存、支持超大图渐进式加载、完美适配 RecyclerView 列表复用、自动释放内存(Activity 销毁时无需手动处理),还支持 GIF/WEBP 动图、图片裁剪 / 圆角等特效,是中大型 Android 项目的主流图片加载框架之一。

下面从依赖引入、基础配置、核心用法、高频场景、高级定制、避坑点 全维度讲解,适配Gradle Kotlin DSL(build.gradle.kts) 和 Kotlin 语法,代码可直接复制使用,覆盖 99% 的开发场景。

一、核心优势(为什么选 Fresco)

对比 Glide/Picasso,Fresco 的核心优势集中在内存优化大尺寸图片处理

  1. 内存占用极低 :图片默认存储在Ashmem(匿名共享内存),而非 Java 堆,避免 OOM(内存溢出),尤其适合加载高清图 / 长图;
  2. 自动缓存策略:三级缓存(内存 / 磁盘 / 网络),可自定义缓存规则,支持断点续传;
  3. 动图原生支持:无需额外依赖,直接加载 GIF/WEBP 动图,支持暂停 / 播放;
  4. 渐进式加载 :超大图(如长图、高清海报)可像网页一样从模糊到清晰渐进加载,提升用户体验;
  5. 生命周期绑定:与 Activity/Fragment 生命周期自动绑定,页面销毁时自动停止加载、释放资源,无需手动处理;
  6. 丰富的图片特效:内置圆角、圆形、裁剪、淡入淡出等效果,无需自定义 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:91:1
fresco:fadeDuration 淡入动画时长 300(ms)
fresco:progressBarImage 渐进式加载进度条 本地资源
fresco:roundWithOverlayColor 圆角边缘色 @color/white(解决透明图锯齿)

注意:SimpleDraweeViewwrap_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):底层自动构建默认的ImageRequestDraweeController,满足 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 常用高级配置说明

  1. 内存缓存 :默认按设备内存自动分配,自定义时建议设置为50-200MB
  2. 磁盘缓存 :建议放在 App 私有目录(getExternalFilesDir),无需存储权限,App 卸载时自动删除;
  3. 降采样(Downsample) :开启后 Fresco 会根据SimpleDraweeView的尺寸自动缩放图片,避免加载原图导致内存浪费;
  4. 拦截器 :通过 OkHttp3 的拦截器可统一添加Token、User-Agent等请求头,或添加日志拦截器调试网络请求。

七、Fresco 核心类关系(快速理解)

为了避免混淆,简单梳理 Fresco 的核心类职责,帮助理解整体流程:

  1. Fresco:全局入口类,负责初始化、获取全局配置;
  2. SimpleDraweeView:图片展示控件,替代 ImageView,处理布局和特效;
  3. ImageRequest:图片请求类,封装图片地址、加载规则、超时、缓存等配置;
  4. DraweeController:加载控制器,绑定 ImageRequest 和 SimpleDraweeView,控制加载 / 暂停 / 复用;
  5. ImagePipeline:核心加载引擎,处理三级缓存、网络请求、图片解码、内存管理;
  6. 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/setImageBitmapSimpleDraweeView无效,且会覆盖 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会报权限错误,建议:

  • 加载相册图片使用ContentProvidercontent://协议);
  • 自定义缓存路径使用 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% 的问题都能解决:

  1. 检查 Fresco 是否初始化 :确认自定义 Application 已注册,且Fresco.initialize(this)已执行;
  2. 检查网络权限 :加载网络图片必须添加<uses-permission android:name="android.permission.INTERNET" />
  3. 检查 Uri 格式 :不同数据源的 Uri 协议是否正确(如 Assets 是asset:///,3 个 /);
  4. 检查依赖是否完整 :加载动图需添加animated-gif/animated-webp扩展包;
  5. 检查 SimpleDraweeView 属性 :是否正确设置layout_width/layout_heightwrap_content是否配合viewAspectRatio
  6. 检查网络链接 :是否是https链接(Android 9.0+ 默认禁止 http),或是否开启明文网络支持;
  7. 检查日志 :查看 Logcat 的Fresco/ImagePipeline相关日志,定位具体错误(如权限、网络超时、图片地址无效);
  8. 清理缓存 :Fresco 有默认缓存,可通过Fresco.getImagePipeline().clearCaches()清理缓存后重新测试;
  9. 检查混淆规则: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,对大图片处理无特殊要求。

十一、总结(核心关键点)

  1. 核心步骤:添加依赖 → 配置权限 → Application 中初始化 Fresco → 布局使用 SimpleDraweeView → 代码中 setImageURI/setController 加载图片;
  2. 核心控件SimpleDraweeView是 Fresco 的核心,替代 ImageView,支持 XML 配置圆角 / 圆形 / 占位图;
  3. 核心用法 :极简加载用setImageURI(uri),自定义配置用ImageRequest+DraweeController
  4. 列表优化 :RecyclerView 中必须调用setOldController()重用旧控制器,防止图片闪烁;
  5. 高级定制 :通过ImagePipelineConfig替换 OkHttp3 网络层、自定义缓存大小、添加拦截器;
  6. 避坑核心:全局初始化一次、用 Application 上下文、不设置 src 属性、动图页面销毁时暂停;
  7. 动图支持 :添加animated-gif/animated-webp扩展包,通过Animatable接口控制播放 / 暂停。
相关推荐
TheNextByte12 小时前
如何在Android上恢复已删除的联系人
android
my_power5202 小时前
安卓面试题总结
android
恋猫de小郭2 小时前
小米 HyperOS 4 大变样?核心应用以 Rust / Flutter 重写,不兼容老系统
android·前端·人工智能·flutter·ios
JMchen1232 小时前
Android TCP连接实战:详解一个高效可靠的TCP客户端实现
android·java·经验分享·网络协议·tcp/ip·移动开发·android-studio
灯火不休ᝰ2 小时前
[安卓] Kotlin中的架构演进:从MVC到MVVM
android·架构·kotlin
JMchen1232 小时前
AR Core与CameraX的融合:测量应用从原理到实现
android·经验分享·程序人生·ar·移动开发·android studio·camerax
June bug2 小时前
【领域知识】一个休闲游戏产品(安卓和iOS)从0到1
android·ios
zgyhc20502 小时前
【Android Audio】Android Audio有线设备插拔监听机制
android
ZHANG13HAO2 小时前
android13 系统强制wifi连接到内网,假装具有互联网能力
android