मैं थोड़ी देर के लिए dagger2 के साथ काम कर रहा हूं। और मुझे प्रत्येक गतिविधि / परिहास के लिए एक घटक / मॉड्यूल बनाने के लिए भ्रमित किया गया। कृपया मुझे यह स्पष्ट करने में मदद करें:
उदाहरण के लिए, हमारे पास एक ऐप है, और ऐप में लगभग 50 स्क्रीन हैं। हम DI के लिए MVP पैटर्न और Dagger2 के बाद कोड लागू करेंगे। मान लीजिए कि हमारे पास 50 गतिविधियाँ और 50 प्रस्तुतकर्ता हैं।
मेरी राय में, आमतौर पर हमें इस तरह कोड व्यवस्थित करना चाहिए:
एक AppComponent और AppModule बनाएं जो सभी ऑब्जेक्ट प्रदान करेगा जो ऐप के खुले रहने पर उपयोग किया जाएगा।
@Module public class AppModule { private final MyApplicationClass application; public AppModule(MyApplicationClass application) { this.application = application; } @Provides @Singleton Context provideApplicationContext() { return this.application; } //... and many other providers } @Singleton @Component( modules = { AppModule.class } ) public interface AppComponent { Context getAppContext(); Activity1Component plus(Activity1Module module); Activity2Component plus(Activity2Module module); //... plus 48 methods for 48 other activities. Suppose that we don't have any other Scope (like UserScope after user login, ....) }
गतिविधि बनाएँ:
@Scope @Documented @Retention(value=RUNTIME) public @interface ActivityScope { }
प्रत्येक गतिविधि के लिए घटक और मॉड्यूल बनाएँ। आमतौर पर मैं उन्हें गतिविधि वर्ग के भीतर स्थिर वर्ग के रूप में रखूँगा:
@Module public class Activity1Module { public LoginModule() { } @Provides @ActivityScope Activity1Presenter provideActivity1Presenter(Context context, /*...some other params*/){ return new Activity1PresenterImpl(context, /*...some other params*/); } } @ActivityScope @Subcomponent( modules = { Activity1Module.class } ) public interface Activity1Component { void inject(Activity1 activity); // inject Presenter to the Activity } // .... Same with 49 remaining modules and components.
वे सिर्फ यह दिखाने के लिए बहुत सरल उदाहरण हैं कि मैं इसे कैसे लागू करूंगा।
लेकिन मेरे एक दोस्त ने मुझे एक और कार्यान्वयन दिया:
प्रस्तुतकर्ता बनाएँ जो सभी प्रस्तुतकर्ता प्रदान करेगा:
@Module public class AppPresenterModule { @Provides Activity1Presenter provideActivity1Presentor(Context context, /*...some other params*/){ return new Activity1PresenterImpl(context, /*...some other params*/); } @Provides Activity2Presenter provideActivity2Presentor(Context context, /*...some other params*/){ return new Activity2PresenterImpl(context, /*...some other params*/); } //... same with 48 other presenters. }
AppModule और AppComponent बनाएं:
@Module public class AppModule { private final MyApplicationClass application; public AppModule(MyApplicationClass application) { this.application = application; } @Provides @Singleton Context provideApplicationContext() { return this.application; } //... and many other provides } @Singleton @Component( modules = { AppModule.class, AppPresenterModule.class } ) public interface AppComponent { Context getAppContext(); public void inject(Activity1 activity); public void inject(Activity2 activity); //... and 48 other methods for 48 other activities. Suppose that we don't have any other Scope (like UserScope after user login, ....) }
उनकी व्याख्या है: उन्हें प्रत्येक गतिविधि के लिए घटक और मॉड्यूल बनाने की आवश्यकता नहीं है। मुझे लगता है कि मेरे दोस्तों का विचार बिल्कुल अच्छा नहीं है, लेकिन अगर मैं गलत हूं तो कृपया मुझे सुधारें। ये कारण हैं:
बहुत सारी मेमोरी लीक :
- यदि उपयोगकर्ता के पास केवल 2 गतिविधियां खुली हैं, तो भी ऐप 50 प्रस्तुतकर्ता बनाएगा।
- उपयोगकर्ता द्वारा किसी गतिविधि को बंद करने के बाद, उसका प्रस्तुतकर्ता अभी भी बना रहेगा
यदि मैं एक गतिविधि के दो उदाहरण बनाना चाहता हूं तो क्या होगा? (वह दो प्रस्तुतकर्ता कैसे बना सकता है)
ऐप को इनिशियलाइज़ करने में बहुत समय लगेगा (क्योंकि इसमें कई प्रेज़ेंटर्स, ऑब्जेक्ट्स, बनाने के लिए है ...)
लंबे पोस्ट के लिए क्षमा करें, लेकिन कृपया मुझे और मेरे दोस्त को यह स्पष्ट करने में मदद करें, मैं उसे मना नहीं सकता। आपकी टिप्पणियों की बहुत सराहना की जाएगी।
/ ------------------------------------------------- ---------------------- /
डेमो करने के बाद संपादित करें।
सबसे पहले, @pandawarrior उत्तर के लिए धन्यवाद। मुझे यह प्रश्न पूछने से पहले एक डेमो बनाना चाहिए था। मुझे उम्मीद है कि यहां मेरा निष्कर्ष किसी और की मदद कर सकता है।
- मेरे दोस्त ने जो किया है वह मेमोरी लीक का कारण नहीं बनता है जब तक कि वह किसी भी स्कोप को प्रोवाइड्स-मेथड्स में न डाले। (उदाहरण के लिए @ सिसलिंग, या @ यूसरस्कोप, ...)
- हम कई प्रस्तुतकर्ता बना सकते हैं, यदि प्रोवाइड-विधि में कोई स्कोप नहीं है। (तो, मेरा दूसरा बिंदु भी गलत है)
- डैगर प्रेजेंटर्स तभी बनाएंगे जब उनकी जरूरत होगी। (इसलिए, ऐप को इनिशियलाइज़ करने में ज़्यादा समय नहीं लगेगा, मैं लज़ीज़ इंजेक्शन से भ्रमित हो गया था)
इसलिए, ऊपर बताए गए सभी कारण ज्यादातर गलत हैं। लेकिन इसका यह मतलब नहीं है कि हमें दो कारणों से अपने मित्र विचार का पालन करना चाहिए:
यह स्रोत की वास्तुकला के लिए अच्छा नहीं है, जब वह मॉड्यूल / घटक में सभी प्रस्तुतकर्ताओं को सम्मिलित करता है। (यह इंटरफ़ेस अलगाव सिद्धांत का उल्लंघन करता है , हो सकता है कि सिंगल रिस्पॉन्सिबिलिटी प्रिकेटर भी)।
जब हम एक स्कोप कम्पोनेंट बनाते हैं, तो हमें पता चलेगा कि यह कब बना है और कब नष्ट हो गया है जो मेमोरी लीक से बचने के लिए बहुत बड़ा लाभ है। इसलिए, प्रत्येक गतिविधि के लिए हमें @ActivityScope के साथ एक घटक बनाना चाहिए। आइए कल्पना करें, मेरे दोस्तों के कार्यान्वयन के साथ, कि हम प्रदाता-विधि में कुछ स्कोप रखना भूल गए => मेमोरी लीक होगी।
मेरी राय में, एक छोटे से ऐप के साथ (कई निर्भरता के बिना या समान निर्भरता के साथ कुछ ही स्क्रीन), हम अपने दोस्तों के विचार को लागू कर सकते हैं, लेकिन निश्चित रूप से यह अनुशंसित नहीं है।
पर अधिक पढ़ने के लिए पसंद करते हैं: डैगर 2 में एक घटक (वस्तु ग्राफ) के जीवनचक्र को क्या निर्धारित करता है? Dagger2 गतिविधि क्षेत्र, मुझे कितने मॉड्यूल / घटकों की आवश्यकता है?
और एक और ध्यान दें: यदि आप देखना चाहते हैं कि जब वस्तु नष्ट हो जाती है, तो आप उन तरीकों को एक साथ कॉल कर सकते हैं और जीसी तुरंत चलेगा:
System.runFinalization();
System.gc();
यदि आप इन विधियों में से केवल एक का उपयोग करते हैं, तो जीसी बाद में चलेगा, और आपको गलत परिणाम मिल सकते हैं।
ControllerModule
एक नया निर्माण करेगाPresenter
और फिर प्रस्तुतकर्ता कोActivity
या में इंजेक्ट किया जाएगाFragment
। इसके पक्ष में या इसके खिलाफ कोई ठोस राय?