Poignard pour Android: Injection d'une Activité à l'objet graphique après l'appel de setContentView
Je veux utiliser la Dague sur Android pour injecter une instance d'un Activity
dans une autre classe comme suit:
class PresentationLayer{
Activity mActivity;
@Inject
public PresentationLayer(Activity activity){
this.mActivity = activity;
}
public void presentData(User user){
((TextView)mActivity.findViewById(R.id.username))
.setText(user.getName());
//...
//...
}
}
Je suis en mesure de faire l'injection, mais tous les domaines de la Activity
sont null
au moment de l'injection.
Voici comment j'ai fais l'injection:
Mon Activity
est un module en lui-même.
@Module(
complete = false
)
class MainActivity extends Activity{
@Override
public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.main_activity);
ObjectGraph objectGraph = CustomApplication.getObjectGraph();
PresentationLayer pres = objectGraph.get(PresentationLayer.class);
}
@Provides Activity provideActivity(){
return this;
}
}
C'est mon module principal
@Module(
entryPoints = PresentationLayer.class,
includes = MainActivity.class
)
class DaggerModule{
@Provides PresentationLayer providePresentation(Activity activity){
return new PresentationLayer(activity);
}
}
Et mon Application
classe qui amorce le graphe d'objets.
class CustomApplication extends Application{
private static ObjectGraph sObjectGraph;
@Override
public void onCreate(){
sObjectGraph = ObjectGraph.create(new DaggerModule());
}
static getObjectGraph(){
return sObjectGraph;
}
}
Je suis à la recherche d'un moyen d'exécuter explicitement l'injection après j'appelle setContentView
.
Comment dois-je faire?
EDIT 1:
Je l'ai eu à travailler comme ça - mais je ne suis pas sûr si c'est le "droit chemin". Ce que je fais est
- Passer de l'Activité pour l'
Module
constructeur - Assurer que je construis la
ObjectGraph
après je nesetContentView()
de sorte qu'un bonActivity
instance est transmise à laObjectGraph
.
Mon Activity
n'est plus un poignard Module
.
Cela se traduit par les éléments suivants dans le code:
@Module(
entryPoints = PresentationLayer.class
)
class DaggerModule{
private Activity mActivity;
public DaggerModule (Activity activity){
this.mActivity = activity;
}
@Provides PresentationLayer providePresentation(){
return new PresentationLayer(mActivity);
}
}
Et c'est ainsi que ma Activity
ressemble:
class MainActivity extends Activity{
@Override
public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.main_activity);
ObjectGraph objectGraph = CustomApplication.getObjectGraph(this);
PresentationLayer pres = objectGraph.get(PresentationLayer.class);
User user = //get the user here
pres.presentData(user);
}
}
Cette solution semble répondre aux points soulevés par Jesse Wilson dans cette réponse. Cependant, je suis préoccupé par la performance, car le ObjectGraph
va être construit chaque fois que le Activity
est créé.
Toutes les pensées?
OriginalL'auteur curioustechizen | 2012-12-21
Vous devez vous connecter pour publier un commentaire.
Malheureusement, cela ne va pas probablement travailler avec un Poignard, ou avec la plupart des autres d'injection de dépendance des cadres. Le problème, c'est que le cycle de vie de
Activity
n'est pas proprement la ligne avec le cycle de vie dePresentationLayer
. Par exemple, lorsque vous faites pivoter votre écran, Android va détruire l'activité et en créer un autre à sa place. Il n'y a pas de crochet pourPresentationLayer
à y participer.À la Place, nous avons été à l'aide de Otto pour communiquer entre les activités et leurs backends et il a bien fonctionné. Voir Eric Burke exemple de code projet pour un exemple.
Activity
cycle de vie. J'ai édité ma question inclure ce que je pense est une solution possible. Aimerions avoir votre avis sur cela. Mon but est de partager des modules entre un ordinateur de bureau application Java et une application Android. Ainsi, laPresentationLayer
serait une dépendance pour uneBusinessLogicLayer
. Dans Android, j'ai configurer Poignard à injecter de l'Android à la mise en œuvre de PresentationLayer, tandis que dans la JSE, j'injecte un autre impl de PresLayer (qui ne nécessite pas deActivity
car il utilise justeSystem.out.println
). Je serais ravi d'en télécharger un exemple de projet sur github si ça aide.ObjectGraph création à bas prix, mais votre singletons peuvent ne pas l'être. Surtout si elles sont dynamiques (comme les Otto bus) dans ce cas, vous ne voulez pas créer plusieurs objets graphiques. Avec ObjectGraph.signe plus(), vous pouvez appuyer sur des graphiques existants. Qui peuvent aider à créer par l'activité graphique.
Merci! En fonction de vos commentaires, je me penche vers l'utilisation d'une approche hybride de l'utilisation de la Dague là où il est "facile" et à se rabattre sur "manuel" DI où à l'aide de la Dague (ou tout JSR330 bibliothèque) devient lourd. Par manuel DI, je veux dire soit de la construction de l'objet de ma classe de bootstrap (comme un
main
méthode ouServlet
ouonCreate()
etc); ou en utilisant des usines pour obtenir les occurrences de dépendances à chaque fois que nécessaire. Ce n'est pas l'idéal, mais je pense que c'est un compromis acceptable dans mon cas d'utilisation.OriginalL'auteur Jesse Wilson