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

时间:2018-03-28 01:04:00

标签: java android dependency-injection dagger-2 dagger

我正在尝试在Dagger 2中传递Application context Activity。我们非常感谢任何帮助!我最后提供了我的Logcat控制台。

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

我还尝试根据此问题进行改进:https://github.com/google/dagger/issues/832

没有任何效果!我知道在Activity中实际上不需要Application上下文,因为Activity中有Activity上下文。但只是好奇学习如何在任何类中传递Application上下文(例如,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注入上下文)

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中使用任何类型的构造函数注入,如下所示。

 private NannyApplication nannyApplication;

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

这就是我使用注射的原因:

@Inject NannyApplication nannyApplication; //Problem here

2 个答案:

答案 0 :(得分:0)

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

规则:对于任何服务组件T,我们必须将{T}的实例作为seedInstance提供给AndroidInjector.Builder<T>类。这意味着如果您在MainActivity的生命周期回调中执行AndroidInjector.inject(this),则会在seedInstance = mainActivity类中初始化AndroidInjector.Builder<MainActivity>

这个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);
    }
}

答案 1 :(得分:-2)

在应用程序类中进行一些更改,如下所示......

public class NannyApplication extends Application {
private DaggerNannyApplicationComponent daggerNannyApplicationComponent;

@Override
public void onCreate() {
    super.onCreate();
    daggerNannyApplicationComponent.builder().create().build();
}

public DaggerNannyApplicationComponent getComponent() {
    return daggerNannyApplicationComponent;
}

}