7

come dice il titolo, sto cercando di capire qual è il modo migliore per iniettare una dipendenza in un frammento. Voglio essere indipendente da framework esterni come RoboGuice ecc.Iniezione frammento Android e Dipendenza

Ora, nel modo più semplice possibile, ho un'interfaccia che astrae un qualche tipo di logica e, da un'attività, voglio iniettare un'implementazione di questo interfaccia. So che devo fornire un costruttore predefinito per il mio frammento, dal momento che il sistema potrebbe dover ricreare il frammento ad un certo punto e che il solito modo di creare una nuova istanza del frammento è quello di fornire un metodo statico che gestisca la creazione come this:

public static Fragment newInstance() { 
    final Bundle bundle = new Bundle(); 
    ... 
    final Fragment fragment = new MyFragment(); 
    fragment.setArguments(bundle); 
    return fragment; 
} 

Come posso passare la mia dipendenza al frammento? Dovrei farlo implementare le interfacce Parcelable o Serializable e quindi comprimerlo nel Bundle? C'è un altro modo per raggiungere il risultato?

Grazie!

risposta

0

Perché non prendi la dipendenza dalla tua attività?

public void onActivityCreated(Bundle b){ 
    super.onActivityCreated(b) 
    DependencyClass c = ((MyActivity)getActivity()).getDependency(); 
} 
+1

Se mi piace questo finirò accoppiando il frammento alla giusta attività? Voglio ancora che il frammento sia indipendente e riutilizzabile. – TheImplementer

7

Una soluzione semplice è dichiarare un'interfaccia che sta dichiarando le dipendenze richieste per il frammento. Quindi, il contesto del frammento implementa questa interfaccia e esegue il polling delle dipendenze quando necessario dal contesto.

contratto:

public interface MyDependencies { 

    MyDep getDep(); 

} 

attività:

public MyActivity extends Activity implements MyDependencies { 

    @Override 
    public MyDep getDep(){ 
     return createMyDependencyOrGetItFromASingletonOrGetItFromApplication() 
    } 
} 

Frammento:

public void onActivityCreated(Bundle b){ 
    super.onActivityCreated(b) 

    if (getActivity() instanceOf MyDependencies) { 
     MyDep dep = ((MyDependencies) getActivity).getDep(); 
    } else { 
     throw new RuntimeException("Context does not support the Fragment, implement MyDependencies") 
    } 
} 

Così, in effetti, non c'è accoppiamento necessario l'attività perché il contratto è definito da un'interfaccia

0

Se non è possibile passare la dipendenza tramite il costruttore (se è necessario un costruttore predefinito) e non si desidera utilizzare una lib di dipendenza come Dagger o RoboGuice, l'altro modo classico è un setter per "iniettare" la dipendenza.

Fragment MyFragment { 

Depend mDepend; 

.... 


    public void setDepend(Depend depend) { 
     mDepend = depend; 
    } 

} 

Quindi nella propria attività è possibile iniettare la dipendenza nel metodo onCreate.

quindi qualcosa di simile nella vostra attività:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_map); 
    MapFragment wrapperFragment = new WrapperFragment(); 
    if (savedInstanceState == null) { 
     getFragmentManager().beginTransaction() 
       .add(R.id.map_container, wrapperFragment).commit(); 
    // find the fragment 
    // call the setter 
    } 
} 
+0

Il problema con questa soluzione è che quando Android ricrea il frammento utilizza il costruttore predefinito e non chiama i metodi impostati, anche se sono stati chiamati in precedenza. – FacundoJ

Problemi correlati