java - 在 Dagger 2 的 Activity 中传递应用程序上下文 (NullPointerException)

标签 java android dependency-injection dagger-2 dagger

我正在尝试在 Dagger 2 中传递应用程序上下文 Activity。非常感谢任何帮助!我在最后提供了我的 Logcat 控制台。

Gregory Kick 的项目给了我同样的问题,如下所示的最后一个错误部分。 https://github.com/gk5885/dagger-android-sample

我也尝试过基于这个问题进行改进:https://github.com/google/dagger/issues/832

没有任何作用!我知道实际上, Activity 中不需要应用程序上下文,因为 Activity 中存在 Activity 上下文。但只是想知道如何在任何类(例如 Activity)中传递应用程序上下文?

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    buildToolsVersion "27.0.3"

    testBuildType "staging"

    testOptions {
        reportDir "$rootDir/test-reports"
        resultsDir "$rootDir/test-results"
        unitTests {
            returnDefaultValues true
            all {
                // Sets JVM argument(s) for the test JVM(s).
                jvmArgs '-XX:MaxPermSize=256m'

                // You can also check the task name to apply options to only the tests you specify.
                if (it.name == 'testDebugUnitTest') {
                    systemProperty 'debug', 'true'
                }
            }
        }
    }
    defaultConfig {
        applicationId "com.nexuslab.forensics.grr.nanny"
        minSdkVersion 21
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        testHandleProfiling true
        testFunctionalTest true
    }
    signingConfigs {
        debugKey {
            keyAlias 'android'
            keyPassword 'android'
            storeFile file('keys/platform.jks')
            storePassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debugKey
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        staging {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:27.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    compileOnly 'org.projectlombok:lombok:1.16.20'
    annotationProcessor 'org.projectlombok:lombok:1.16.20'
    //java vm based test
    testImplementation 'org.hamcrest:hamcrest-core:1.3'
    testImplementation 'junit:junit:4.12'
    testImplementation 'org.powermock:powermock-api-mockito:1.6.5'
    testImplementation 'org.powermock:powermock-module-junit4-rule-agent:1.6.5'
    testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.5'
    testImplementation 'org.powermock:powermock-module-junit4:1.6.5'
    testImplementation 'org.mockito:mockito-core:2.15.0'
    //instrumentation test
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    androidTestImplementation 'com.android.support:support-annotations:27.1.0'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test:rules:1.0.1'
    androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
    androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
    androidTestImplementation 'junit:junit:4.12'
    //dagger 2
    implementation 'com.google.dagger:dagger:2.14.1'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
    //to enable DaggerActivity, DaggerBroadcastReceiver, DaggerFragment etc classes
    implementation 'com.google.dagger:dagger-android:2.14.1'
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1'
    //support libraries with dagger 2
    implementation 'com.google.dagger:dagger-android-support:2.14.1'
    implementation 'com.android.support:support-v4:27.1.0'
}

应用程序类(NannyApplication.java)

package com.nexuslab.forensics.grr.nanny;

import android.app.Application;

import com.nexuslab.forensics.grr.nanny.di.component.DaggerNannyApplicationComponent;
/**
 * Created by gaute on 3/25/18.
 */

public class NannyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerNannyApplicationComponent.builder().create(this);
    }
}

MainActivity.java(在这里,我想从 NannyApplication.java 注入(inject)上下文)

package com.nexuslab.forensics.grr.nanny;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import javax.inject.Inject;

/**
 * @author gaute
 */
public class MainActivity extends AppCompatActivity {

    @Inject
    NannyApplication nannyApplication;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Utils.schedule(nannyApplication, HeartbeatService.class, Constants.HEARTBEAT_CHECK_INTERVAL);
        finishAndRemoveTask();
    }

}

Dagger 应用程序组件 (NannyApplicationComponent.java)

package com.nexuslab.forensics.grr.nanny.di.component;


import com.nexuslab.forensics.grr.nanny.NannyApplication;
import com.nexuslab.forensics.grr.nanny.di.module.NannyApplicationModule;

import javax.inject.Singleton;

import dagger.Component;
import dagger.android.AndroidInjector;

/**
 * Created by gaute on 3/25/18.
 */

@Singleton
@Component(modules = NannyApplicationModule.class)
public interface NannyApplicationComponent extends AndroidInjector<NannyApplication> {

    @Component.Builder
    abstract class Builder extends AndroidInjector.Builder<NannyApplication> {
    }
}

应用程序模块(NannyApplicationModule.java)

package com.nexuslab.forensics.grr.nanny.di.module;

import com.nexuslab.forensics.grr.nanny.NannyApplication;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import dagger.android.AndroidInjectionModule;

@Module(includes = AndroidInjectionModule.class)
public class NannyApplicationModule {

    @Provides
    @Singleton
    NannyApplication getNannyApplication(NannyApplication nannyApplication) {
        return nannyApplication;
    }

}

错误,我得到了

03-27 19:08:37.107 10619-10619/com.nexuslab.forensics.grr.nanny E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.nexuslab.forensics.grr.nanny, PID: 10619
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nexuslab.forensics.grr.nanny/com.nexuslab.forensics.grr.nanny.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String[] com.nexuslab.forensics.grr.nanny.NannyApplication.databaseList()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3046)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1688)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6809)
        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:767)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String[] com.nexuslab.forensics.grr.nanny.NannyApplication.databaseList()' on a null object reference
        at com.nexuslab.forensics.grr.nanny.MainActivity.onStart(MainActivity.java:26)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1412)
        at android.app.Activity.performStart(Activity.java:7015)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2909)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3046) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1688) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6809) 
        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:767) 

我无法在 Activity 中使用任何类型的构造函数注入(inject),如下所示。

 private NannyApplication nannyApplication;

    @Inject
    public MainActivity() {
        this.nannyApplication = nannyApplication;
    }

这就是我使用归档注入(inject)的原因:

@Inject NannyApplication nannyApplication; //Problem here

最佳答案

这是一个有效的解决方案。

规则:对于任何服务组件 T ,我们必须将 T 的实例提供为 seedInstance进入AndroidInjector.Builder<T>类(class)。这意味着如果你这样做AndroidInjector.inject(this)在 MainActivity 的生命周期回调中,您初始化了 seedInstance = mainActivity里面AndroidInjector.Builder<MainActivity>类(class)。

这个AndroidInjector.Builder<MainActivity> ,您将在 DaggerNannyApplicationComponent's Builder 内看到内部类因为,在 NannyApplicationComponent ,你会写

@Component.Builder /* Simply tells this Builder is DaggerNannyApplicationComponent’s inner Builder class */
    abstract class Builder extends AndroidInjector.Builder<NannyApplication> {
    } 

Github 中的示例项目:https://github.com/uddhavgautam/Dagger2ApplicationContextToActivity

NannyApplicationComponent.java

@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class /* it makes Dagger generates DaggerNannyApplicationComponent */,
        ApplicationBindingModule.class /* it generats AndroidInjector.Builder<MainActivity>, which
        is used to inject requested dependencies by MainActivity */
})
public interface NannyApplicationComponent extends AndroidInjector<NannyApplication> {

    @Component.Builder /* Simply tells this Builder is DaggerNannyApplicationComponent’s inner Builder class */
    abstract class Builder extends AndroidInjector.Builder<NannyApplication> {
    }
}

ApplicationBindingModule.java

 @Module
    public interface ApplicationBindingModule {

/* These two lines, actually, makes Dagger generates ApplicationBindingModule_MainActivity class */
        @ContributesAndroidInjector
        MainActivity mainActivity();
    }

NannyApplicationModule.java

@Module
public class NannyApplicationModule {
}

MainActivity.java

//MainActivity is a consumer because it has requested nannyApplication using @Inject annotation
public class MainActivity extends DaggerAppCompatActivity {

    @Inject
    NannyApplication nannyApplication /* You got the ApplicationContext */;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // AndroidInjection.inject(this); 
/* if Consumers want MainActivity instance then uncomment AndroidInjection.inject(this) line. Doing this makes MainActivity Consumer as well as Service component. Because it consumed nannyApplication but it has also provided (serviced) it's instance to the external world */
    }

    @Override
    protected void onStart() {
        super.onStart();
        //check nannyApplication
        Log.i("Cls-loader: ", nannyApplication.getClassLoader() + "");
    }
}

NannyApplication.java

public class NannyApplication extends DaggerApplication {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    /**
     * applicationInjector() gets called inside onCreate()
     */
    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        return DaggerNannyApplicationComponent
                .builder()
                .create(this);
    }
}

关于java - 在 Dagger 2 的 Activity 中传递应用程序上下文 (NullPointerException),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49524544/

相关文章:

java - 在 Apache Tomcat 上运行时出现 FileNotFound 异常?

java - 添加 MediaPlayer 会使我的应用程序崩溃 - 无法输出声音

javascript - Angular 2注入(inject)全局依赖

java - 使用 applicationcontext.getbean 与 @configurable 的优势

dependency-injection - Azure 函数 V3 无法使用 EF 核心 5.0-rc1 加载文件或程序集 Microsoft.Extensions.DependencyInjection.Abstractions,版本 = 5.0.0.0

java - 为具有不同模式的多个数据库生成 jOOQ 代码

java - Spring Boot - 是自动注入(inject)的单个实现类

java - 逗号运算符在 "eval()"中做什么?

java - 从 Android 的 Facebook API 的返回响应中获取特定数据

android - 为什么启动 Activity - 焦点在我的 EditText 上,我无法删除它?