6

Per un normale (frammento non annidata) Io uso il seguente approccioCome iniettare dipendenza dal frammento Android nidificato?

1) creare le dipendenze (...) metodo di fissazione dipendenze del frammento

class MyFragment extends MyFragment { 
     void dependencies(Deps deps); 
} 

2) nell'attività di MyFragment genitore onAttachFragment() metodo che ho appena fornire dipendenze per frammento

class MyActivity{ 
    void onAttachFragment(Fragment f){ 
     ((MyFragment)f).dependencies(deps); 
    } 
} 

per frammento nidificato non c'è più onAttachFragment frammento chiamato. Fornire dipendenze per il frammento solo per fornire le dipendenze per il frammento nidificato sembra essere molto ingombrante. Quindi, come potrei fornire delle dipendenze per questo?

+0

Utilizzare dagger2? È stato progettato per gestire questo tipo di cose –

+0

Mimmo Grottoli, so di dagger2. Ma è solo una libreria per eliminare il codice boilerplate dell'iniezione di dipendenza. Ci dovrebbe sempre essere il modo di iniettare dipendenze per costruttore o metodo speciale. – wilddev

+0

Un costruttore di frammenti o attività che inietta alcune dipendenze?Certo che puoi provare, ma alla fine scoprirai che il pugnale o il pugnale2 sono le cose migliori che puoi sviluppare da te (almeno, questo è vero per me) –

risposta

1

Basta tenere le logiche gerarchia, e dovrebbe essere qualcosa di simile:

class MyActivity{ 
    void onAttachFragment(Fragment f){ 
     ((MyFragment)f).dependencies(deps); 
    } 
} 

class MyFragment extends MyFragment { 
     void dependencies(Deps deps) { 
      //TODO: do dependencies of my fragment before 
      ((MyNestedFragment)childF).nestedDependencies(deps); 
      //TODO: do dependencies of my fragment after 
     } 
} 

class MyNestedFragment extends MyNestedFragment { 
     void nestedDependencies(Deps deps); 
} 
+0

È molto strano iniettare dipendenze in MyFragment, perché non ne ha bisogno. MyFragment non dipende da deps. – wilddev

+0

Qual è il punto della domanda allora? –

+0

Iliiaz Akhmedov, MyFragment non dipende da deps, ma MyNestedFragment sì! Quindi passare a MyFragment è antipattern. – wilddev

2

Se MyFragment dipende MyNestedFragment, e MyNestedFragment dipende Deps; Ne consegue che MyFragment dipende anche da Deps. Ovviamente, nessuna istanza di Activity.onAttachFragment() viene invocata quando Activity.onAttachFragment() viene chiamato, quindi è necessario attendere fino a dopo aver gonfiato il layout in MyFragment.onCreateView() prima di fornire MyNestedFragment con le sue dipendenze.

public class MyActivity { 

    ... 

    void onAttachFragment(Fragment f){ 
     ((MyFragment)f).dependencies(deps); 
    } 

    public static class MyFragment extends Fragment { 

     private Deps deps; 

     void dependencies(Deps deps) { 
      this.deps = deps; 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
      View rootView = inflater.inflate(R.layout.fragment_main, container, false); 

      // <fragment> element in fragment_main layout has 
      // android:tag set to nested_fragment 
      ((MyNestedFragment)getChildFragmentManager() 
       .findFragmentByTag("nested_fragment")) 
       .dependencies(this.deps); 

      return rootView; 
     } 
    } 

    public static class MyNestedFragment extends Fragment { 

     void dependencies(Deps deps) { 
      ... 
     } 
    } 

    ... 
} 

Se tutto questo sembra un po 'confuso, è perché i frammenti non sono POJO si può semplicemente cablare in qualche modo arbitrario. I loro cicli di vita devono essere gestiti da FragmentManager annidati. Se crei i tuoi frammenti a livello di codice anziché utilizzare l'elemento <frammento>, avrai un po 'più di controllo sul loro ciclo di vita al costo di una maggiore complessità.

Se si desidera trattare Android come un contenitore CIO, quindi RoboGuice può essere quello che stai cercando:

public class MyActivity extends roboguice.activity.RoboFragmentActivity { 

    ... 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

     // This only needs to be called once for the whole app, so it could 
     // be in the onCreate() method of a custom Application subclass 
     RoboGuice.setUseAnnotationDatabases(false); 

     super.onCreate(savedInstanceState); 

     setContentView(R.layout.activity_main); 
    } 

    public static class MyNestedFragment extends Fragment { 

     @Inject 
     private Deps deps; 

     @Override 
     public void onAttach(Activity activity) { 
      super.onAttach(activity); 
      // this isn't necessary if you extend RoboFragment 
      roboguice.RoboGuice.getInjector(activity).injectMembers(this); 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

      //This would not even be possible in the previous example 
      // because onCreateView() is called before dependencies() 
      // can be called. 
      deps.method(); 

      View rootView = inflater.inflate(R.layout.fragment_nested, container, false); 
      return rootView; 
     } 
    } 
} 

@Singleton 
public class Deps { 
    public void method() { 
     System.out.println("Deps.method()"); 
    } 
} 
5

solo farlo fuori contesto, che sarà un'attività. Crea un getter per le dipendenze della tua attività. I frammenti hanno accesso all'attività principale, se nidificati o meno. Trasmetti il ​​contesto e chiama il getter per ottenere le dipendenze dall'attività nidificata.

+0

Per credito extra crea un'interfaccia ComponentProvider e chiedi alla tua attività di implementarla, che espone un metodo singolo getComponent. Il getContext deve essere trasmesso all'interfaccia anziché a un'attività specifica che consente il riutilizzo dei frammenti attraverso le attività. – FriendlyMikhail

2

Si tenta di impostare le dipendenze, quando i frammenti sono collegati. Invece di questo, cerca di ottenere le dipendenze dal frammento quando necessario. C'è un esempio:

public class MyActivity extends Activity { 

    public Deps getDepsForFragment(Fragment fragment) { 
     if (fragment instanceof MyFragment) { 
      return depsForMyFragment; 
     } else if (fragment instanceof MyNestedFragment) { 
      return depsForMyNestedFragment; 
     } else { 
      return null; 
     } 
    } 
} 

public class MyFragment extends Fragment { 

    private Deps deps; 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     try { 
      MyActivtiy myActivity = (MyActivtiy) context; 
      deps = myActivity.getDepsForFragment(this); 
     } catch (ClassCastException e) { 
      throw new ClassCastException("This fragment attached to an activity which can't provide the required dependencies."); 
     } 
    } 
} 

// this is the same as the MyFragment 
public class MyNestedFragment extends Fragment { 

    private Deps deps; 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     try { 
      MyActivtiy myActivity = (MyActivtiy) context; 
      deps = myActivity.getDepsForFragment(this); 
     } catch (ClassCastException e) { 
      throw new ClassCastException("This fragment attached to an activity which can't provide the required dependencies."); 
     } 
    } 
} 

Naturalmente, si può fare il metodo separata per dipendenze get dell'attività (come getDepsForMyFragment e getDepsForMyNestedFragment).