6

Pour une méthode ordinaire (fragment non imbriqué) J'utilise l'approche suivanteComment injecter une dépendance à un fragment androïde imbriqué?

1) créer des dépendances (...) pour définir les dépendances de fragment

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

2) dans l'activité des parents MyFragment onAttachFragment() méthode que je me contente de fournir des dépendances pour le fragment

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

pour fragment imbriqué il n'y a pas plus fragment onAttachFragment appelé. Fournir des dépendances pour fragment juste pour fournir des dépendances pour fragment imbriqué semble être très lourd. Alors, comment pourrais-je fournir des dépendances pour cela?

+0

Utilisez dagger2? Il a été conçu pour gérer ce genre de choses –

+0

Mimmo Grottoli, je sais dagger2. Mais c'est juste une bibliothèque pour éliminer le code standard de l'injection de dépendance. Il devrait toujours être possible d'injecter des dépendances par constructeur ou par une méthode spéciale. – wilddev

+0

Un constructeur de fragments ou d'activités qui injecte une dépendance?Bien sûr, vous pouvez essayer, mais à la fin, vous trouverez que poignard ou dague2 sont les meilleures choses que vous pouvez développer par vos propres moyens (au moins, c'est vrai pour moi) –

Répondre

1

Il suffit de garder la logique hiérarchique, et il devrait être quelque chose comme ceci:

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

Il est très étrange d'injecter des dépendances à MyFragment, car il n'en a pas besoin. MyFragment ne dépend pas de deps. – wilddev

+0

Quel est le point de la question alors? –

+0

Iliiaz Akhmedov, MyFragment ne dépend pas de deps, mais MyNestedFragment fait! Donc passer des deps à MyFragment est antipattern. – wilddev

2

Si MyFragment dépend de MyNestedFragment et MyNestedFragment dépend de Deps; il s'ensuit que MyFragment dépend également de Deps. Bien sûr, aucune instance de MyNestedFragment n'existe lorsque Activity.onAttachFragment() est appelée, vous devrez donc attendre après avoir gonflé la mise en page dans MyFragment.onCreateView() avant de fournir MyNestedFragment avec ses dépendances.

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) { 
      ... 
     } 
    } 

    ... 
} 

Si tout cela semble un peu en désordre, c'est parce que les fragments ne sont pas POJO vous pouvez simplement câbler d'une certaine manière arbitraire. Leurs cycles de vie doivent être gérés par des gestionnaires de fragments imbriqués. Si vous créez vos fragments par programme plutôt que d'utiliser l'élément <fragment>, vous aurez un peu plus de contrôle sur leur cycle de vie au prix de plus de complexité.

Si vous voulez traiter Android comme un conteneur IoC, alors RoboGuice peut-être ce que vous cherchez:

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

Il suffit de le faire hors du contexte qui sera une activité. Créer un getter pour les dépendances sur votre activité. Les fragments ont accès à l'activité parent, imbriquée ou non. Convertissez le contexte, puis appelez le getter pour obtenir les dépendances dans l'activité imbriquée.

+0

Pour un crédit supplémentaire, créez une interface ComponentProvider et demandez à votre activité de l'implémenter, ce qui expose une seule méthode getComponent. Le getContext doit être casté sur l'interface plutôt que sur une activité spécifique permettant la réutilisation de fragments à travers les activités. – FriendlyMikhail

2

Vous essayez de définir les dépendances, lorsque les fragments sont attachés. Au lieu de cela, essayez d'obtenir les dépendances du fragment en cas de besoin. Il est un exemple:

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."); 
     } 
    } 
} 

Bien sûr, vous pouvez faire pour la méthode DEPS séparée get dans l'activité (comme getDepsForMyFragment et getDepsForMyNestedFragment).