Kann ich einfach die Superklasse injizieren, wenn ich dagger2 für die Abhängigkeitsinjektion verwende?

Lesezeit: 5 Minuten

Ich verwende Dagger2 für DI in meiner Android-Anwendung. Ich habe festgestellt, dass ich für jede Klasse, die das @Inject-Feld verwendet, eine Inject-Methode schreiben muss. Gibt es eine Möglichkeit, dass ich einfach die übergeordnete Klasse injizieren kann, damit ich nicht inject für jede Unterklasse aufrufen muss? Nehmen Sie zum Beispiel Aktivität. Ich habe ein BaseActivity von dem jede Aktivität ausgeht. Gibt es eine Möglichkeit, einfach eine Inject-Methode in der Komponente für BaseActivity zu erstellen und einfach inject in BaseActivitys onCreate aufzurufen, und @inject-Felder in Unteraktivitäten werden automatisch injiziert?

  • Könnten Sie einen Beispielcode hinzufügen, um zu zeigen, was Sie meinen?

    – nhaarman

    28. März 2015 um 11:49 Uhr

  • Nur eine Frage (wenn ich Ihre Frage richtig verstanden habe), warum definieren Sie das Injektionsfeld nicht in der Basisaktivität und verwenden es in der untergeordneten Aktivität. Jeder solche Fall, in dem Sie möchten, dass Ihre “Inject-Felder in Unteraktivitäten automatisch injiziert werden”

    – JSONParser

    10. Oktober 2019 um 4:57 Uhr

Benutzer-Avatar
Gordak

Ich bin auf die gleiche Situation gestoßen. Eine Möglichkeit, die Injektion einer gemeinsamen Komponente in allen Aktivitäten etwas zu erleichtern, ist die folgende:

1) Erweitern Sie die Application-Klasse, um die gemeinsame Komponente erstellen und einen Verweis darauf beibehalten zu können.

public class ApplicationDagger extends Application {

    private ApplicationComponent component;

    @Override
    public void onCreate(){
        super.onCreate();
        component = DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build();
    }

    public ApplicationComponent getComponent(){
            return component;
    }
}

2) Erstellen Sie eine abstrakte DaggerActivity, die die gemeinsame Komponente von Application erhält und eine abstrakte Methode aufruft injectActivity, wobei die Komponente als Argument angegeben wird. So was:

public abstract class DaggerActivity extends Activity {

    @Override
    public void onCreate(Bundle saved){
        super.onCreate(saved);
        ApplicationComponent component = ((ApplicationDagger) getApplication()).getComponent();
        injectActivity(component);
    }

    public abstract void injectActivity(ApplicationComponent component);
}

3) Zuletzt müssen Sie tatsächlich jeden spritzen Activity verlängern DaggerActivity. Aber das geht jetzt mit weniger Aufwand, da man das umsetzen muss abstract -Methode andernfalls erhalten Sie Kompilierungsfehler. Auf geht’s:

public class FirstActivity extends DaggerActivity {

    @Inject
    ClassToInject object;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //initialize your Activity
    }

    @Override
    public void injectActivity(ApplicationComponent component) {
        component.inject(this);
    }
}

Natürlich müssen Sie trotzdem jede Aktivität explizit in Ihrer Komponente deklarieren.

UPDATE: Injizieren von @ActivityScope-Objekten in Fragmente

Irgendwann musste ich konsumieren benutzerdefinierte Bereiche Objekte an ein binden
Activity Lebenszyklus. Ich habe mich entschieden, diesen Beitrag zu erweitern, da er einigen Leuten helfen könnte.

Nehmen wir an, Sie haben eine @Modul Klasse ActivityModule und ein @Unterkomponente Schnittstelle ActivityComponent.

Sie müssten die ändern DaggerActivity. Das Activities verlängern DaggerActivity müssten die neue Methode implementieren (Änderung der Signatur).

public abstract class ActivityDagger extends AppCompatActivity {

    ActivityComponent component;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        component = ((ApplicationDagger) getApplication()).getComponent().plus(new ActivityModule(this));
        injectActivity(component);
        super.onCreate(savedInstanceState);
    }

    ActivityComponent getComponent() {
        return component;
    }

    public abstract void injectActivity(ActivityComponent component);
}

Dann eine Klasse FragmentDagger verlängern Fragment kann so erstellt werden:

public abstract class FragmentDagger extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityDagger activityDagger = (ActivityDagger) getActivity();
        ActivityComponent component = activityDagger.getComponent();
        injectFragment(component);
    }

    public abstract void injectFragment(ActivityComponent component);

}

Wie für die Activitiesdas Fragments verlängern FragmentDagger haben nur eine Methode zu implementieren:

public abstract void injectFragment(ActivityComponent component);

Sie sollten in der Lage sein, wiederzuverwenden Fragments wo immer Sie wollen. Beachten Sie, dass die Methode super.onCreated() in ActivityDagger sollte nach der Komponenteninstanziierung aufgerufen werden. Sonst bekommt man NullPointerException wenn der Activity Zustand wird neu erstellt, weil die Methode super.onCreate() des Fragment wird angerufen werden.

Benutzer-Avatar
Kirill Bojarschinow

Es ist derzeit nicht möglich. Erklärung von Gregory Kick (ab hier):

So funktionieren die Injektionsmethoden für Mitglieder:

  1. Sie können eine Injektionsmethode für Mitglieder für jeden Typ erstellen, der vorhanden ist @Inject irgendwo in seiner Klassenhierarchie. Wenn dies nicht der Fall ist, erhalten Sie eine Fehlermeldung.
  2. Alle @Injected Members in der gesamten Typhierarchie werden eingefügt: der Argumenttyp und alle Supertypen.
  3. Es werden keine Mitglieder sein @Injected für Untertypen des Argumenttyps.

Dieses Thema wurde diskutiert hier und hier, folgen Sie diesen für Updates. Aber es ist unwahrscheinlich, dass sich das bald ändert, denn Dagger 2 ist es kurz vor der Freigabe.

  • Es scheint, dass sie diese Entscheidung aus einem bestimmten Grund getroffen haben. Aber es ist immer noch schade, dass sie dies nicht unterstützen, da es meiner Meinung nach ein wenig kontraintuitiv ist. Trotzdem danke für die Antwort!

    – Chris.Zou

    5. April 2015 um 5:19 Uhr

  • @Chris.Zou Um die Injektion von Unterklassen zu unterstützen, müssten Sie zur Laufzeit reflektieren. Das Dagger 2-Team hat schon früh entschieden, dass es Dinge zur Laufzeit vermeiden wollte, da es langsamer ist und Sie Fehler erst erfahren, wenn Sie die App ausführen.

    – vaughandroid

    22. Juni 2015 um 11:24 Uhr

Sie können einen kleinen Hack mit Reflektion machen:

public class UiInjector {

    private static final String METHOD_NAME = "inject";

    private final UIComponent component;

    public UiInjector(final UIComponent component) {
        this.component = component;
    }

    public void inject(final Object subject) {
        try {
            component.getClass()
                    .getMethod(METHOD_NAME, subject.getClass())
                    .invoke(component, subject);
        } catch (final NoSuchMethodException exception) {
            throwNoInjectMethodForType(component, subject.getClass());
        } catch (final Exception exception) {
            throwUnknownInjectionError(exception);
        }
    }

    private void throwNoInjectMethodForType(final Object component, final Class subjectType) {
        throw new RuntimeException(component.getClass().getSimpleName() +
                " doesn't have inject method with parameter type : " + subjectType);
    }

    private void throwUnknownInjectionError(final Exception cause) {
        throw new RuntimeException("Unknown injection error", cause);
    }
}

In diesem Fall müssen Sie immer noch die Inject-Methode in eine Komponente schreiben, aber Sie brauchen die ‘Inject’-Methode nicht in jeder Aktivität, jedem Fragment, jeder Ansicht oder was auch immer.

Warum ist es Arbeit? wenn wir verwenden getClass() auf Injektionssubjekt erhält eine Nachkommenklasse, keine Basis.

Vorsicht! Falls Sie Proguard verwenden, müssen Sie als nächstes hinzufügen
-keep class <ComponentClass> { *; } an Ihre Regeln anpassen, um die Inject-Methoden unverändert in der Komponente beizubehalten

  • Der Dolch soll zur Kompilierzeit überprüft werden, also wird dies diesen Zweck zunichte machen …

    – AA_PV

    9. Juni 2020 um 12:29 Uhr

1109190cookie-checkKann ich einfach die Superklasse injizieren, wenn ich dagger2 für die Abhängigkeitsinjektion verwende?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy