2014-10-23 4 views
5

Ho un'applicazione Mortar, con un MortarActivityScope come primo figlio nell'ambito della radice. Il MortarActivityScope ha un ActivityScope che @Provides un'attività per classi iniettati:Come @Provide un'attività per MortarActivityScope, senza perdere l'attività sulle modifiche di orientamento?

@Module(addsTo = ApplicationModule.class, injects = {Foo.class, SomePresenter.class, AnotherPresenter.class}) 
public class ActivityModule { 

    private final Activity activity; 

    public ActivityModule(Activity activity) { 
     this.activity = activity; 
    } 

    @Provides Activity provideActivity() { 
     return activity; 
    } 
} 

public class Foo { 
    private final Activity activity; 
    @Inject(Activity activity) { 
     this.activity = activity; 
    } 
    public void doSomethingWithActivity() { 
     // do stuff with activity: findViewById(), getWindow(), mess with action bar etc. 
    } 
} 

Questo va bene fino a quando un cambiamento di orientamento succede. Nel progetto di esempio del mortaio, l'ambito dell'attività non viene distrutto nelle modifiche di orientamento. Ciò presumibilmente consente ai presentatori, agli schermi ecc. Di @Singleton di persistere attraverso i cambiamenti di orientamento. Si può vedere questo nel metodo OnDestroy() in attività principale del progetto di esempio:

@Override protected void onDestroy() { 
    super.onDestroy(); 

    actionBarOwner.dropView(this); 

    // activityScope may be null in case isWrongInstance() returned true in onCreate() 
    if (isFinishing() && activityScope != null) { 
     MortarScope parentScope = Mortar.getScope(getApplication()); 
     parentScope.destroyChild(activityScope); 
     activityScope = null; 
    } 
    } 
} 

Tuttavia, facendo in questo modo significa che la vecchia ObjectGraph persiste attraverso i cambiamenti di orientamento. Ho notato che Mortar.requireActivityScope non sostituisce il modulo dal vecchio ambito di attività con il nuovo modulo fornito dal nuovo Blueprint. Invece, il grafico dell'oggetto conserva un riferimento al modulo precedente, inclusa l'attività distrutta.

public class MyActivity extends Activity implements Blueprint { 

    @Inject foo; 

    @Override protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     MortarScope parentScope = Mortar.getScope(getApplication()); 
     activityScope = Mortar.requireActivityScope(parentScope, this); 
     Mortar.inject(this, this); 

     foo.doSomethingWithActivity(); //fails, because activity injected by object graph is destroyed 
    } 

    @Override 
    public String getMortarScopeName() { 
     return getClass().getName(); 
    } 

    @Override 
    public Object getDaggerModule() { 
     return new ActivityModule(this); 
    } 
} 

L'attività di campionamento Mortaio sembra per aggirare il problema non includendo un metodo @Provides Activity nel modulo principale. Ma il MortarActivityScope non dovrebbe essere in grado di iniettare un'attività? Qual è il modo migliore per farlo senza perdere tutti gli oggetti singleton (Presenter oggetti, ecc.) Sul cambio di orientamento?

risposta

5

Non consentire a nessuno di iniettare l'attività, che non può essere reso sicuro. Invece iniettare un presentatore che è legato all'attività.

How to handle onActivityResult() with Mortar include un esempio di un'attività in possesso di un relatore. Altre parti della tua app, inclusi altri presentatori, possono quindi iniettare quella e chiederle di fare tutto ciò di cui hanno bisogno per svolgere l'attività.

E non è necessario collegare tutto il lavoro specifico dell'attività in un singolo presentatore di attività. La nostra attività ha diversi presentatori che mediano i propri servizi al resto dell'app.

+0

Molto elegante. L'uso di un Presenter iniettato è un percorso che non avevo mai considerato, ed è molto meno contabile rispetto all'aggiornamento manuale di ogni oggetto che contiene un riferimento all'attività. – weefbellington

Problemi correlati