Я пытаюсь передать Activity из контекста приложения в Dagger 2. Любая помощь приветствуется !! В конце я предоставил свою консоль Logcat.
Проект Грегори Кика дает мне ту же проблему, что и показано ниже в последнем разделе об ошибках. 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)
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
@DavidMedenjak, спасибо! Для меня немного сложно понять фреймворк, созданный Dagger 2. Я решил проблему. Я опубликую обновленный ответ со всеми подробностями объяснения, чтобы он действительно помог всем, кто склоняется к Dagger 2.
Я только что создал образец проекта для этой проблемы, чтобы он помог другим пользователям, которые ждут моего ответа. github.com/uddhavgautam/Dagger2ApplicationContextToActivity




внесите некоторые изменения в класс приложения, как показано ниже ...
public class NannyApplication extends Application {
private DaggerNannyApplicationComponent daggerNannyApplicationComponent;
@Override
public void onCreate() {
super.onCreate();
daggerNannyApplicationComponent.builder().create().build();
}
public DaggerNannyApplicationComponent getComponent() {
return daggerNannyApplicationComponent;
}
}
daggerNannyApplicationComponent.builder().create().build(); неверен, поскольку builder() - статический метод. Во-вторых, зачем мне здесь метод getComponent(), ведь я нигде не использую daggerNannyApplicationComponent.
Если вы хотите, я предлагаю одну демонстрацию для базы данных комнат с использованием dagger 2.
Это рабочее решение.
Правило: для любого служебного компонента T мы должны предоставить экземпляр T как seedInstance в класс AndroidInjector.Builder<T>. Это означает, что если вы выполняете AndroidInjector.inject(this) внутри обратного вызова жизненного цикла MainActivity, вы инициализировали 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();
}
НяняApplicationModule.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);
}
}
Я вижу пустой
onCreateи не звоню наactivityComponent.inject(activity). Куда вы вкладываете свою активность?@Injectне будет вводить какие-либо поля без вызываемого компонента.