Android में डिपेंडेंसी इंजेक्शन

डिपेंडेंसी इंजेक्शन (डीआई) एक ऐसी तकनीक है जिसका बड़ी मात्रा में प्रोग्रामिंग और Android डेवलपमेंट के हिसाब से बनाया गया है. डीआई के सिद्धांतों का पालन करके, बुनियादी काम कर रहे हैं.

डिपेंडेंसी इंजेक्शन को लागू करने के ये फ़ायदे हैं:

  • कोड को फिर से इस्तेमाल करना
  • रीफ़ैक्टरिंग में आसानी
  • टेस्ट करने में आसान

डिपेंडेंसी इंजेक्शन के बारे में बुनियादी बातें

खास तौर पर, Android में डिपेंडेंसी इंजेक्शन को कवर करने से पहले, यह पेज डिपेंडेंसी इंजेक्शन के काम करने के तरीके के बारे में ज़्यादा जानकारी.

डिपेंडेंसी इंजेक्शन क्या है?

क्लास में अक्सर अन्य क्लास के रेफ़रंस की ज़रूरत होती है. उदाहरण के लिए, Car क्लास इसके लिए, Engine क्लास के रेफ़रंस की ज़रूरत पड़ सकती है. इन ज़रूरी क्लास को कॉल किया जाता है डिपेंडेंसी सेट अप की गई है और इस उदाहरण में Car क्लास जिसमें Engine क्लास का इंस्टेंस हो.

क्लास के लिए ज़रूरी ऑब्जेक्ट को पाने के तीन तरीके हैं:

  1. क्लास अपनी ज़रूरत के हिसाब से डिपेंडेंसी बनाती है. ऊपर दिए गए उदाहरण में, Car इसके लिए अपना इंस्टेंस बनाएगा और शुरू करेगा Engine.
  2. उसे किसी और जगह से पकड़ें. कुछ Android API, जैसे Context गैटर और getSystemService(), इसे लागू करें तरीका है.
  3. इसे पैरामीटर के तौर पर उपलब्ध कराएं. ऐप्लिकेशन ये सुविधाएं दे सकता है डिपेंडेंसी जब क्लास बनाई जाती है या उन्हें फ़ंक्शन में पास किया जाता है जिन्हें हर डिपेंडेंसी की ज़रूरत होती है. ऊपर दिए गए उदाहरण में, Car कंस्ट्रक्टर को पैरामीटर के तौर पर Engine मिलेगा.

तीसरा विकल्प है डिपेंडेंसी इंजेक्शन! इस तरीके से, आपको एक क्लास की डिपेंडेंसी और क्लास की बजाय उन्हें उपलब्ध कराना उन्हें अपने आप मिल जाता है.

यहां एक उदाहरण दिया गया है. डिपेंडेंसी इंजेक्शन के बिना, Car का प्रतिनिधित्व करता है जो कोड में अपनी Engine डिपेंडेंसी बनाता है, इस तरह दिखता है:

Kotlin

class Car {

    private val engine = Engine()

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.start()
}

Java

class Car {

    private Engine engine = new Engine();

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}
डिपेंडेंसी इंजेक्शन के बिना कार क्लास

यह डिपेंडेंसी इंजेक्शन का उदाहरण नहीं है, क्योंकि Car क्लास खुद का Engine बना रहा है. इससे समस्या हो सकती है, क्योंकि:

  • Car और Engine आपस में जुड़े हैं - Car का उदाहरण, एक का इस्तेमाल करता है Engine टाइप का इस्तेमाल किया जा सकता है. साथ ही, इसे आसानी से कोई सब-क्लास या अन्य तरीके से लागू नहीं किया जा सकता इस्तेमाल किया गया. अगर Car को अपना Engine बनाना होता, तो आपको के बजाय दूसरी तरह के सर्च इंजन के लिए एक ही Car का दोबारा इस्तेमाल करने के बजाय दो तरह के Car इस्तेमाल करते हैं Gas और Electric.

  • Engine पर हार्ड डिपेंडेंसी होने की वजह से, टेस्टिंग और मुश्किल हो जाती है. Car, Engine का रीयल इंस्टेंस, इस तरह से आप अलग-अलग टेस्ट केस के लिए, Engine में बदलाव करने के लिए टेस्ट डबल का इस्तेमाल करें.

डिपेंडेंसी इंजेक्शन के साथ कोड कैसा दिखता है? हर इंस्टेंस के बजाय शुरू करने पर, Car अपना Engine ऑब्जेक्ट बनाता है. हालांकि, इसे Engine ऑब्जेक्ट, अपने कंस्ट्रक्टर में पैरामीटर के तौर पर:

Kotlin

class Car(private val engine: Engine) {
    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val engine = Engine()
    val car = Car(engine)
    car.start()
}

Java

class Car {

    private final Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Engine engine = new Engine();
        Car car = new Car(engine);
        car.start();
    }
}
डिपेंडेंसी इंजेक्शन का इस्तेमाल करने वाली कार क्लास

main फ़ंक्शन, Car का इस्तेमाल करता है. Car, Engine पर निर्भर करता है. इसलिए, यह ऐप्लिकेशन इंस्टेंस Engine का इंस्टेंस होता है और फिर इसका इस्तेमाल Car के इंस्टेंस को बनाने के लिए करता है. कॉन्टेंट बनाने डीआई की मदद से काम करने वाले इस मॉडल के ये फ़ायदे हैं:

  • Car का फिर से इस्तेमाल किया जा सकता है. आप Engine के अलग-अलग तरीके से लागू करके Car. उदाहरण के लिए, आप Engine का एक नया सब-क्लास परिभाषित कर सकते हैं, जिसे ElectricEngine, जिसे आपको Car को इस्तेमाल करने की अनुमति देनी है. अगर डीआई का इस्तेमाल किया जाता है, तो आपको सिर्फ़ अपडेट की गई ElectricEngine सब-क्लास के इंस्टेंस में पास करने पर भी Car अब भी काम करता है वह भी बिना किसी अतिरिक्त बदलाव के.

  • Car को आसानी से टेस्ट किया जा सकता है. अलग-अलग टेस्ट में पास होने के लिए, . उदाहरण के लिए, आपEngine FakeEngine को कॉन्फ़िगर करें और इसे अलग-अलग टेस्ट के लिए कॉन्फ़िगर करें.

Android में डिपेंडेंसी इंजेक्शन करने के दो मुख्य तरीके हैं:

  • कंस्ट्रक्टर इंजेक्शन. यह तरीका ऊपर बताया गया है. आप किसी क्लास की डिपेंडेंसी और उसके कंस्ट्रक्टर के लिए.

  • फ़ील्ड इंजेक्शन या सेटर इंजेक्शन. Android फ़्रेमवर्क की कुछ क्लास जैसे ऐक्टिविटी और फ़्रैगमेंट, सिस्टम से इंस्टैंशिएट किए जाते हैं. इसलिए, कंस्ट्रक्टर इंजेक्शन नहीं लगाया जा सकता. फ़ील्ड इंजेक्शन के साथ, डिपेंडेंसी इंस्टैंशिएट की जाती है क्लास बनाने के बाद. कोड इस तरह दिखेगा:

Kotlin

class Car {
    lateinit var engine: Engine

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.engine = Engine()
    car.start()
}

Java

class Car {

    private Engine engine;

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.setEngine(new Engine());
        car.start();
    }
}

अपने-आप डिपेंडेंसी इंजेक्शन

पिछले उदाहरण में, आपने डिपेंडेंसी बनाई, दी, और उन्हें मैनेज किया की मदद ली जा सकती है. इसे कहा जाता है हाथ से डिपेंडेंसी इंजेक्शन या मैन्युअल डिपेंडेंसी इंजेक्शन. Car में उदाहरण के लिए, सिर्फ़ एक डिपेंडेंसी थी. हालांकि, ज़्यादा डिपेंडेंसी और क्लास डिपेंडेंसी को मैन्युअल तरीके से डालने की प्रोसेस को ज़्यादा थका देना. मैन्युअल डिपेंडेंसी इंजेक्शन इसमें कई समस्याएं भी मौजूद हैं:

  • बड़े ऐप्लिकेशन के लिए, सभी डिपेंडेंसी लेकर उन्हें कनेक्ट करें बड़ी मात्रा में बॉयलरप्लेट कोड की ज़रूरत पड़ सकती है. कई लेयर वाली आर्किटेक्चर का इस्तेमाल करना चाहते हैं, तो सबसे ऊपर की लेयर के लिए ऑब्जेक्ट बनाने के लिए, आपको सभी पर निर्भर होता है. एक ठोस उदाहरण के तौर पर, दुनिया भर हो सकता है कि आपको असली कार के इंजन, ट्रांसमिशन, चेसिस, और दूसरे पुर्ज़ों की ज़रूरत पड़े; और उसके बदले में एक इंजन को सिलिंडर और स्पार्क प्लग की ज़रूरत होती है.

  • जब आप डिपेंडेंसी पास करने से पहले उन्हें बनाने में असमर्थ हों — तो उदाहरण के लिए, अपने फ़्लो के लिए लेज़ी इनिशलाइज़ेशन या ऑब्जेक्ट की स्कोपिंग ऐप्लिकेशन — तो आपको एक कस्टम कंटेनर (या डिपेंडेंसी) जो मेमोरी में आपकी डिपेंडेंसी के लाइफ़टाइम को मैनेज करती है.

कुछ ऐसी लाइब्रेरी हैं जो डिपेंडेंसी बनाना और उपलब्ध कराना. ये दो कैटगरी में आते हैं:

  • रिफ़्लेक्शन पर आधारित समाधान, जो रनटाइम के दौरान डिपेंडेंसी कनेक्ट करते हैं.

  • डिपेंडेंसी कनेक्ट करने के लिए कोड जनरेट करने वाले स्टैटिक सलूशन इकट्ठा करने के दौरान.

डैगर, Java के लिए एक लोकप्रिय डिपेंडेंसी इंजेक्शन लाइब्रेरी है. Kotlin और Android, जिन्हें Google मैनेज करता है. डैगर की मदद से डीआईवाई का इस्तेमाल किया जा सकता है डिपेंडेंसी का ग्राफ़ बनाकर और उसे मैनेज करके. यह यह पूरी तरह से स्टैटिक और कंपाइल-टाइम डिपेंडेंसी देता है, जो रिफ़्लेक्शन पर आधारित समाधानों के डेवलपमेंट और परफ़ॉर्मेंस से जुड़ी समस्याएं, जैसे कि गुआस.

डिपेंडेंसी इंजेक्शन के विकल्प

डिपेंडेंसी इंजेक्शन का एक विकल्प, सेवा लोकेटर के साथ भी काम कर सकते हैं. सर्विस लोकेटर का डिज़ाइन पैटर्न भी कंक्रीट डिपेंडेंसी से क्लास को अलग करने में मदद करता है. आप एक क्लास बनाते हैं इसे सर्विस लोकेटर भी कहा जाता है, जो डिपेंडेंसी बनाता और सेव करता है. इसके बाद ज़रूरत के हिसाब से डिपेंडेंसी उपलब्ध कराती है.

Kotlin

object ServiceLocator {
    fun getEngine(): Engine = Engine()
}

class Car {
    private val engine = ServiceLocator.getEngine()

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.start()
}

Java

class ServiceLocator {

    private static ServiceLocator instance = null;

    private ServiceLocator() {}

    public static ServiceLocator getInstance() {
        if (instance == null) {
            synchronized(ServiceLocator.class) {
                instance = new ServiceLocator();
            }
        }
        return instance;
    }

    public Engine getEngine() {
        return new Engine();
    }
}

class Car {

    private Engine engine = ServiceLocator.getInstance().getEngine();

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

सर्विस लोकेटर पैटर्न, डिपेंडेंसी इंजेक्शन से अलग है इस्तेमाल किए जा सकने वाले एलिमेंट हो सकते हैं. सर्विस लोकेटर पैटर्न के साथ, क्लास में ऑब्जेक्ट को कंट्रोल करना और उन्हें इंजेक्ट करने के लिए कहना; डिपेंडेंसी इंजेक्शन के ज़रिए, इस ऐप्लिकेशन के पास ज़रूरी चीज़ों को इंजेक्ट करने का कंट्रोल है.

डिपेंडेंसी इंजेक्शन की तुलना में:

  • सर्विस लोकेटर के लिए ज़रूरी डिपेंडेंसी के कलेक्शन से कोड बनता है इसे टेस्ट करना मुश्किल है, क्योंकि सभी टेस्ट को एक ही ग्लोबल साइट से इंटरैक्ट करना होता है सर्विस लोकेटर.

  • डिपेंडेंसी को क्लास लागू करने के दौरान एन्कोड किया जाता है, एपीआई प्लैटफ़ॉर्म में नहीं. इससे यह पता लगाना मुश्किल होता है कि किसी क्लास को बाहर से क्या चाहिए. इस वजह से, Car या सर्विस लोकेटर में उपलब्ध डिपेंडेंसी से रनटाइम या टेस्ट का नतीजा मिल सकता है से जुड़ी गड़बड़ी हो सकती है.

  • अगर आपको स्कोप के तौर पर सेट करना है, तो ऑब्जेक्ट के लाइफ़टाइम को मैनेज करना ज़्यादा मुश्किल है आपके डिवाइस पर ऐक्टिव रहने वाला कोई भी आइटम उपलब्ध नहीं है.

अपने Android ऐप्लिकेशन में Hilt का इस्तेमाल करें

Hilt Jetpack सुझाया गया है Android में डिपेंडेंसी इंजेक्शन के लिए लाइब्रेरी. हिल्ट, काम करने का एक मानक तरीका बताता है अपने ऐप्लिकेशन में हर Android क्लास के लिए कंटेनर देकर, उसे ध्यान में रखते हुए कार्रवाई करें अपने-आप उनकी लाइफ़साइकल मैनेज करने और उन्हें प्रोजेक्ट करने में मदद करता है.

Hilt को मशहूर डीआई लाइब्रेरी के ऊपर बनाया गया है डैगर: समय में सुधार, रनटाइम की परफ़ॉर्मेंस, बढ़ाए जा सकने की योग्यता, और Android Studio को कंपाइल करें डैगर से मिलने वाली सहायता का प्रचार करता है.

Hilt के बारे में ज़्यादा जानने के लिए देखें Hilt के साथ डिपेंडेंसी इंजेक्शन.

नतीजा

डिपेंडेंसी इंजेक्शन आपके ऐप्लिकेशन के लिए ये फ़ायदे हैं:

  • क्लास का फिर से इस्तेमाल करना और डिपेंडेंसी को अलग करना: बदलना आसान है किसी डिपेंडेंसी को लागू करना. इनवर्सेशन की वजह से, कोड को दोबारा इस्तेमाल करने की प्रोसेस बेहतर हुई है और क्लास से कंट्रोल नहीं होता कि उनकी डिपेंडेंसी कैसे बनाई जाती है, लेकिन इसके बजाय किसी भी कॉन्फ़िगरेशन के साथ काम किया जा सकता है.

  • रीफ़ैक्टरिंग में आसानी: डिपेंडेंसी, एपीआई का ऐसा हिस्सा बन जाती हैं जिसकी पुष्टि की जा सके ताकि ऑब्जेक्ट बनाने के समय या कंपाइल करते समय उनकी जांच की जा सके बल्कि इन्हें लागू करने की जानकारी दें.

  • जांच में आसान: क्लास अपनी डिपेंडेंसी मैनेज नहीं करती. इसलिए, जब आप की जांच कर रहे हैं, तो आप अलग-अलग तरीकों से पास करके हर तरह की चीज़ों की जांच कर सकते हैं को ठीक करने की ज़रूरत नहीं है.

डिपेंडेंसी इंजेक्शन के फ़ायदों के बारे में पूरी तरह से जानने के लिए, इसे आज़माना चाहिए मैन्युअल तरीके से तय करना होगा, जैसा कि मैन्युअल डिपेंडेंसी इंजेक्शन में दिखाया गया है.

अन्य संसाधन

डिपेंडेंसी इंजेक्शन के बारे में ज़्यादा जानने के लिए, नीचे दिए गए अतिरिक्त संसाधन देखें.

सैंपल