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

Dagger2 Android构造函数注入时出现空指针异常求助

嘿,我来帮你排查这个空指针问题,同时聊聊MVP模式下非Activity类获取Context的最优实践~

一、先排查空指针的核心原因

你遇到的空指针大概率是以下几个问题之一:

  1. Component初始化时没传入有效Context
    你需要确保ContextModule的实例是用Application Context(而非Activity Context)初始化的,并且Component构建时正确关联了这个Module。
  2. Interactor是手动new出来的,而非Dagger创建
    如果你自己new MyInteractor(),Dagger根本没机会为它注入Context,自然会是空指针。必须通过Dagger提供的方法获取Interactor实例。
  3. Interactor的注入配置不完整
    要么没给Interactor的构造函数加@Inject注解,要么Component里没声明提供Interactor的方法。

二、正确的Dagger注入示例

我补全你的代码并给出标准实现:

1. 完善ContextModule(你的基础代码没问题,建议明确返回Application Context)

@Module
public class ContextModule {
    private final Context appContext;

    public ContextModule(Context context) {
        // 确保传入的是Application Context,避免内存泄漏
        this.appContext = context.getApplicationContext();
    }

    @Singleton
    @Provides
    public Context provideContext() {
        return appContext;
    }
}

2. 完善Component

@Singleton
@Component(modules = {ContextModule.class})
public interface AppComponent {
    // 提供获取Context的方法(可选,直接注入Interactor更常用)
    Context context();

    // 提供Interactor的实例,或者声明注入方法
    MyInteractor provideMyInteractor();
}

3. Interactor使用构造注入

public class MyInteractor {
    private final Context mContext;

    // 必须加@Inject注解,让Dagger识别这个构造函数
    @Inject
    public MyInteractor(Context context) {
        this.mContext = context;
    }

    // 业务方法示例
    public void loadLocalData() {
        // 安全使用mContext,比如访问SharedPreferences
        SharedPreferences sp = mContext.getSharedPreferences("data", Context.MODE_PRIVATE);
        // ...
    }
}

4. 在Application中初始化Component

public class MyApplication extends Application {
    private AppComponent mAppComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        // 构建Component,传入Application Context
        mAppComponent = DaggerAppComponent.builder()
                .contextModule(new ContextModule(this))
                .build();
    }

    public AppComponent getAppComponent() {
        return mAppComponent;
    }
}

5. 在Presenter中获取Interactor

public class MyPresenter {
    private MyInteractor mInteractor;

    public MyPresenter() {
        // 通过Application的Component获取Interactor实例
        mInteractor = ((MyApplication) getApplication()).getAppComponent().provideMyInteractor();
        // 或者如果Presenter也用构造注入,直接把Interactor作为参数传入更优雅
    }
}

三、非Activity类获取Context的最优方案

在MVP模式下,我推荐以下优先级:

  1. Dagger注入Application Context
    • 优势:符合依赖注入原则,解耦性强,便于单元测试(可以Mock Context),且不会造成内存泄漏(Application Context生命周期和应用一致)。
  2. 通过Application类的静态方法获取Context
    • 这是退而求其次的方案,比如没有用Dagger的场景。但要注意:必须保存Application Context,不要保存Activity Context,且静态方法要保证线程安全。
  3. 绝对避免:通过静态变量持有Activity Context,或者从非注入渠道获取Context,极易引发内存泄漏。

最后再提醒几个注意点

  • 永远优先用Application Context,除非你明确需要Activity的生命周期(比如启动Activity、显示Dialog)。
  • 检查Dagger生成的代码是否正常(Rebuild Project后看有没有DaggerAppComponent类),如果生成失败,大概率是注解配置有误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:29:52