简体   繁体   English

Dagger2 注入未发生 - 注入的字段原来是 null

[英]Dagger2 injection not happening - injected field is turning out to be null

I am struggling with my first Dagger2 project.我正在为我的第一个 Dagger2 项目而苦苦挣扎。

I want to inject a Context into a singleton class.我想将上下文注入 singleton class。 Here is a minimal example (I have removed package names, imports and have not included layouts, values or manifest files).这是一个最小的示例(我已删除 package 名称、导入并且未包含布局、值或清单文件)。 This code ideally should pick up the string <string name="app_name">My Application</string> .理想情况下,此代码应获取字符串<string name="app_name">My Application</string>

MainApplication.java:主要应用。java:

public class MainApplication extends Application {

    private MainComponent mComponent;

    @Override
    public void onCreate() {

        super.onCreate();

        mComponent = DaggerMainComponent.builder()
                .mainModule(new MainModule(this))
                .build();

        getComponent().inject(this);
    }

    public MainComponent getComponent() {

        return mComponent;
    }
}

MainModule.java: MainModule.java:

@Module
public class MainModule {

    private final MainApplication mApplication;

    public MainModule(MainApplication application) {

        this.mApplication = application;
    }

    @Provides
    @Singleton
    public Context getApplicationContext() {

        return mApplication.getApplicationContext();
    }
}

MainComponent.java: MainComponent.java:

@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {

    void inject(MainApplication application);
}

MainActivity.java: MainActivity.java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tvAppName = findViewById(R.id.main_app_name);
        tvAppName.setText(MainHelper.getInstance().getApplicationName());
    }
}

MainHelper.java: MainHelper.java:

public class MainHelper {

    private static final MainHelper INSTANCE = new MainHelper();

    @Inject
    Context mContext;

    public static MainHelper getInstance() {

        return INSTANCE;
    }

    public String getApplicationName() {

        return mContext.getString(R.string.app_name);
    }
}

What actually happens is that I get this exception upon app launch itself:实际发生的是,我在应用程序启动时遇到了这个异常:

2019-11-14 18:46:47.561 9116-9116/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapplication, PID: 9116
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getString(int)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2830)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2909)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1606)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6592)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getString(int)' on a null object reference
        at com.example.myapplication.MainHelper.getApplicationName(MainHelper.java:21)
        at com.example.myapplication.MainActivity.onCreate(MainActivity.java:16)
        at android.app.Activity.performCreate(Activity.java:6984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1235)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2783)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2909) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1606) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6592) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769) 

Basically, the mContext object in MainHelper is null which to me means that the injection didn't work at all.基本上, mContext中的MainHelper是 null 对我来说这意味着注入根本不起作用。 What is going wrong?出了什么问题? This code seems to adhere to pretty much all the tutorials out there.这段代码似乎遵守了几乎所有的教程。

You're not injecting the Context to your MainHelper .您没有将Context注入MainHelper I suggest you refactor your MainHelper class to obtain the Context via Constructor injection (you should do this for all classes you own):我建议您重构您的MainHelper class 以通过构造函数注入获取上下文(您应该为您拥有的所有类执行此操作):

@Singleton
public class MainHelper {

   private final Context context;

   @Inject
   public MainHelper(Context context) {
      this.context = context;
   }

}

The @Inject annotation on the constructor should be enough so that Dagger knows to instantiate/create MainHelper for you.构造函数上的@Inject注释应该足以让 Dagger 知道为您实例化/创建MainHelper And then in order for this MainHelper class to be injected to your MainActivity , you first need to tell Dagger that you need to inject dependencies to your MainActivity .然后为了将这个MainHelper class 注入到您的MainActivity中,您首先需要告诉 Dagger 您需要将依赖项注入到您的MainActivity中。 You already did something similar for your MainApplication class:您已经为MainApplication class 做了类似的事情:

@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {
    void inject(MainApplication application);
    void inject(MainActivity activity);
}

Then on your MainActivity , you inject MainHelper by calling the inject method that Dagger generates for you:然后在您的MainActivity上,通过调用 Dagger 为您生成的inject方法注入MainHelper

public class MainActivity extends AppCompatActivity {

     @Inject
     MainHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ((CustomApplication) getApplication()).getComponent().inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tvAppName = findViewById(R.id.main_app_name);
        tvAppName.setText(helper.getApplicationName());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM