IT knowledge base
CTRL+F per cercare la tua parola chiave

Dagger 2 per sviluppatori Android inesperti. Pugnale 2. Livello avanzato. Parte 2

Questo articolo è la settima parte di una serie di articoli destinati, secondo l'autore, a coloro che non riescono a capire come gestire l' iniezione di dipendenza e il framework Dagger 2 , o semplicemente lo faranno. Scritto originariamente il 30 dicembre 2017. Traduzione gratis.
Immagine del pugnale 2 parte avanzata 2
Questo è il settimo articolo della serie Dagger 2 per sviluppatori Android principianti. ... Se non hai letto i precedenti, allora sei qui .

Serie di articoli

All'inizio della serie

Abbiamo esaminato un progetto di esempio e abbiamo cercato di eliminare le relazioni forti con l'iniezione di dipendenza utilizzando Dagger 2 e annotazioni.
Abbiamo anche esplorato tre nuove annotazioni.@Scope per creare oggetti in una singola istanza (singleton) .@Named per separare i metodi che forniscono oggetti dello stesso tipo.@Qualifier in alternativa@Named ...

Creazione di diversiComponent

Nell'articolo precedente, abbiamo creato dipendenze a livello di applicazione. Ma cosa succede se sono richieste solo le dipendenze di livello?Activity ?Activity viene creato e distrutto nel suo ciclo di vita, ma cosa succede alle dipendenze? Dipendenze create internamenteActivity distrutto insieme aActivity ...
La soluzione migliore è creare moduli e componenti separati per oggetti con cicli di vita diversi.
Per spiegarlo, non voglio aggiungere nuovi oggetti al progetto discusso in precedenza. Invece, considera il nostroMainActivity come oggetto separato e creare il nostro modulo e componente per esso.
Dai un'occhiata alla filialeDagger2Part2 ...

Passaggio 1. Creare un'area di livelloActivity

Per le prossime modifiche, ho creato un pacchetto separato chiamato separateMainActivityFeature ...
Creiamo un nuovo ambito perMainActivity ...
@Scope
public @interface MainActivityScope {}

Passaggio 2. Creazione di un componente perMainActivity

Quindi, creiamo un componente separato (Componente) perMainActivity e contrassegnalo con l'annotazione appena creata.
@Component(dependencies = RandomUserComponent.class)
@MainActivityScope
public interface MainActivityComponent {
    RandomUserAdapter getRandomUserAdapter();
    RandomUsersApi getRandomUserService();
}
Deve essere consentitoMainActivityComponent in riferimento aRandomUserComponent a cosa serve l'attributodependencies ... In altre parole, questo attributo dice a Dagger 2 di fare riferimento aRandomUserComponent se sono necessarie dipendenze aggiuntive.
In questo esempio, al livelloActivity abbiamo bisogno di un adattatore per l'API e un oggetto a cui effettuare chiamateRandomUsersAPI ... Pertanto, implementiamo i metodigetRandomUserAdapter() egetRandomUserService() ...immagine connessione componenti

Passaggio 3. Creazione di un modulo perMainActivity

Ora creiamo un modulo che fornirà l'adattatore.
@Module
public class MainActivityModule {

    private final MainActivity mainActivity;

    public MainActivityModule(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
    }

    @Provides
    @MainActivityScope
    public RandomUserAdapter randomUserAdapter(Picasso picasso){
        return new RandomUserAdapter(mainActivity, picasso);
    }
}
Nota: implementazioneMainActivity tramite adattatore non è necessario, l'ho fatto ad esempio. Se hai bisogno di un contesto perPicasso , quindi puoi usareholder.imageView.getContext() ...
Attenzione all'annotazione@MainActivityScope che si aggiunge al metodorandomUserAdapter() limitare la portata della dipendenza a un livelloActivity ...
È inoltre necessario mappare questo modulo al componente corrispondente. Usiamo l'attributomodules ...
@Component(modules = MainActivityModule.class, dependencies = RandomUserComponent.class)
@MainActivityScope
public interface MainActivityComponent {
    RandomUserAdapter getRandomUserAdapter();
    RandomUsersApi getRandomUserService();
}
Immagine collegata a tutti i componenti e i moduli

Passaggio 4. Creazione di una classeApplication

public class RandomUserApplication extends Application {

    // add the name of this class to the manifest
    private RandomUserComponent randomUserApplicationComponent;

    public static RandomUserApplication get (Activity activity) {
        return (RandomUserApplication) activity.getApplication ();
    }

    @Override
    public void onCreate () {
        super.onCreate ();
        Timber.plant (new Timber.DebugTree ());

        randomUserApplicationComponent = DaggerRandomUserComponent.builder ()
                .contextModule (new ContextModule (this))
                .build ();
    }

    public RandomUserComponent getRandomUserApplicationComponent () {
        return randomUserApplicationComponent;
    }
Questa classe eredita daApplication , contiene tutte le dipendenze a livello di applicazione -RandomUserApplicationComponent ...

Passaggio 5. PerfezionamentoMainActivity

Se crei il progetto, Dagger 2 genererà una classe per teDaggerMainActivityComponent ... Per usare le dipendenze di livelloActivity avremo bisogno di ottenere alcune dipendenze a livello di applicazione.
public class MainActivity extends AppCompatActivity {
...
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ....
    MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
               .mainActivityModule(new MainActivityModule(this))
               .randomUserComponent(RandomUserApplication.get(this).getRandomUserApplicationComponent())
               .build();
    randomUsersApi = mainActivityComponent.getRandomUserService();
    mAdapter = mainActivityComponent.getRandomUserAdapter();
    ....
  }
}
Nota: dai un'occhiata al metodoafterActivityLevelComponent() in filiale con il progetto.

Passaggio 6. Congratulazioni con te stesso

Abbiamo creato un codice abbastanza gestibile. Dipendenze di livello createActivity ... Congratulazioni con te stesso.

Cosa succede se un componente ha 50 dipendenze?

Se ci sono davvero molte dipendenze, dobbiamo scrivere costantemente espressioni come quella qui sotto?randomUserApi = mainActivityComponent.getRandomUserService();
mAdapter = mainActivityComponent.getRandomUserAdapter();
Potresti decidere che questo non è importante per te, ma esiste una soluzione per questo problema.

Utilizzo dell'annotazione@Inject

Invece di dire a Dagger 2 di cosa hai bisognoRandomUserService eRandomUserAdapter , lascia che Dagger 2 elabori il campo che contrassegniamo con l'annotazione@Inject ...
Modificando le classi come di seguito, possiamo iniziare a utilizzare l'annotazione@Inject il prima possibile. Puoi vedere un esempio completo nel thread successivo .

RaffinatezzaMainActivityComponent

Rimuoviamo i metodigetRandomUserService() egetRandomUserAdapter() e aggiungi un metodo per l'iniezioneMainActivity ...
@Component(modules = MainActivityModule.class, dependencies = RandomUserComponent.class)
@MainActivityScope
public interface MainActivityComponent {

    void injectMainActivity(MainActivity mainActivity);
}

RaffinatezzaMainActivity

public class MainActivity extends AppCompatActivity {
  ....
  @Inject
    RandomUsersApi randomUsersApi;

  @Inject
    RandomUserAdapter mAdapter;
  ....
    
   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        .....
        MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
                .mainActivityModule(new MainActivityModule(this))
                .randomUserComponent(RandomUserApplication.get(this).getRandomUserApplicationComponent())
                .build();
        mainActivityComponent.injectMainActivity(this);
        ....
  }
}
Come funziona? Quando Dagger 2 trova un metodo senza valore restituito (void ) capisce che deve esserci qualcosa di cui ha bisogno nella classe, cioè inizializzerà nella classe i campi contrassegnati con l'annotazione@Inject ...
Esattamente quello che serve! Il codice ora può essere eseguito.
GIF
Immagine

Sommario

Abbiamo esaminato un esempio di iniezione di dipendenza a livelloActivity ... Ho visto anche un esempio di utilizzo dell'annotazione@Inject ...

Finalmente

Grazie per aver dedicato del tempo a leggere e supportare questa serie di articoli. Spero che tu abbia una certa comprensione delle dipendenze e di Dagger 2. Il motivo per cui ho scritto questa serie di articoli è perché ho migliorato la mia conoscenza di Dagger 2 leggendo molti articoli su vari blog, ma ho acquisito ancora più conoscenza durante la scrittura di questi articoli. voi. Pertanto, esorto tutti i lettori a condividere le loro conoscenze in ogni modo possibile. Non sono un esperto di Dagger 2, mi considero solo uno studente.
Ora puoi continuare a esplorare ulteriormente Dagger 2, questa serie di articoli dovrebbe averti fornito una comprensione sufficiente di come funziona.

Collegamenti ad altre risorse (in inglese)

  • https://blog.mindorks.com/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b
  • https://blog.mindorks.com/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd
  • https://blog.mindorks.com/the-new-dagger-2-android-injector-cbe7d55afa6a
  • https://blog.mindorks.com/android-dagger2-critical-things-to-know-before-you-implement-275663aecc3e
  • https://blog.mindorks.com/a-complete-guide-to-learn-dagger-2-b4c7a570d99c
  • http://www.vogella.com/tutorials/Dagger/article.html
  • https://medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe