You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Glide 4中如何为自定义ModelLoader获取Context?

在Glide 4中为自定义ModelLoader安全获取Context的正确姿势

刚好之前在项目里折腾过Glide 4自定义ModelLoader的这个问题,踩过内存泄漏的坑,来给你唠唠正确的姿势~

首先你说的没错:绝对不能在ModelLoaderFactory里长期存储Context,不然很容易因为Factory被Glide长期持有,导致Activity这类上下文无法被回收,引发内存泄漏。那怎么把Context传给最终的ModelLoader呢?其实关键就在Factory的构造和build方法的配合上:

核心思路

在registerComponents方法里拿到Context后,把它传给Factory的构造函数,但Factory只做临时中转,不把Context存在成员变量长期持有,而是在build方法创建ModelLoader实例时,直接把Context传递给ModelLoader,同时ModelLoader内部要转存ApplicationContext来避免泄漏。

示例代码

1. 实现ModelLoaderFactory

public class RawModelLoaderFactory implements ModelLoaderFactory<MetadataTest, InputStream> {
    // 注意!这里不要把Context作为Factory的长期成员变量!
    private final Context tempContext;

    // 构造方法临时接收Context,只为中转给ModelLoader
    public RawModelLoaderFactory(Context context) {
        this.tempContext = context;
    }

    @Override
    public ModelLoader<MetadataTest, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
        // 直接把临时Context传给ModelLoader,Factory完成使命就没用了
        return new RawModelLoader(tempContext);
    }

    @Override
    public void teardown() {
        // 无需清理Context,因为Factory没长期持有它
    }
}

2. 实现自定义ModelLoader

public class RawModelLoader implements ModelLoader<MetadataTest, InputStream> {
    private final Context appContext;

    public RawModelLoader(Context context) {
        // 关键操作:转成ApplicationContext,避免持有Activity等上下文导致泄漏
        this.appContext = context.getApplicationContext();
    }

    @Nullable
    @Override
    public LoadData<InputStream> buildLoadData(@NonNull MetadataTest model, int width, int height, @NonNull Options options) {
        // 这里就可以安全地用appContext做资源访问等操作了
        InputStream inputStream = appContext.getResources().openRawResource(model.getResId());
        return new LoadData<>(new ObjectKey(model), new DataFetcher<InputStream>() {
            @Override
            public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
                callback.onDataReady(inputStream);
            }

            @Override
            public void cleanup() {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void cancel() {}

            @NonNull
            @Override
            public Class<InputStream> getDataClass() {
                return InputStream.class;
            }

            @NonNull
            @Override
            public DataSource getDataSource() {
                return DataSource.LOCAL;
            }
        });
    }

    @Override
    public boolean handles(@NonNull MetadataTest model) {
        return true;
    }
}

3. 注册组件

还是用你原来的注册方式就行:

@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    registry.append(MetadataTest.class, InputStream.class, new RawModelLoaderFactory(context));
}

为什么要这么做?

  • Factory是Glide Registry的一部分,生命周期很长,如果存Activity Context,当Activity销毁后,Factory还持有引用就会造成内存泄漏;
  • 我们让Factory只做临时中转,把Context传给ModelLoader后,ModelLoader转存ApplicationContext(ApplicationContext的生命周期和应用一致,不会泄漏),既满足了业务需要,又保证了内存安全。

内容的提问来源于stack exchange,提问作者Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:25:29