लाइब्रेरी के लेखकों के लिए ऑप्टिमाइज़ेशन

लाइब्रेरी के लेखक के तौर पर, आपको यह पक्का करना चाहिए कि ऐप्लिकेशन डेवलपर, ऐप्लिकेशन में आपकी लाइब्रेरी को आसानी से शामिल कर सकें. साथ ही, ऐप्लिकेशन इस्तेमाल करने वाले लोगों को अच्छी क्वालिटी का अनुभव भी मिल सके. आपको यह पक्का करना चाहिए कि आपकी लाइब्रेरी, अतिरिक्त सेटअप के बिना Android के ऑप्टिमाइज़ेशन के साथ काम करती हो. इसके अलावा, यह भी हो सकता है कि लाइब्रेरी, Android पर इस्तेमाल करने के लिए सही न हो.

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

अगर आप ऐप्लिकेशन डेवलपर हैं और आपको अपने Android ऐप्लिकेशन को ऑप्टिमाइज़ करने के बारे में जानना है, तो ऐप्लिकेशन ऑप्टिमाइज़ेशन की सुविधा चालू करना लेख पढ़ें. यह जानने के लिए कि कौनसी लाइब्रेरी इस्तेमाल करना सही है, लाइब्रेरी को समझदारी से चुनना लेख पढ़ें.

रिफ़्लेक्शन के बजाय codegen का इस्तेमाल करना

जब भी हो सके, रिफ़्लेक्शन के बजाय कोड जनरेशन (codegen) का इस्तेमाल करें. प्रोग्रामिंग करते समय, बाउलरप्लेट कोड से बचने के लिए, कोड जनरेशन और रिफ़्लेक्शन, दोनों सामान्य तरीके हैं. हालांकि, R8 जैसे ऐप्लिकेशन ऑप्टिमाइज़र के साथ कोड जनरेशन ज़्यादा काम का है:

  • codegen की मदद से, कोड का विश्लेषण किया जाता है और बिल्ड करने की प्रोसेस के दौरान उसमें बदलाव किया जाता है. कंपाइल होने के बाद, कोड में कोई बड़ा बदलाव नहीं किया जाता. इसलिए, ऑप्टिमाइज़र को पता होता है कि आखिर में किस कोड की ज़रूरत है और किस कोड को सुरक्षित तरीके से हटाया जा सकता है.
  • रिफ़्लेक्शन की मदद से, रनटाइम के दौरान कोड का विश्लेषण किया जाता है और उसमें बदलाव किया जाता है. कोड तब तक पूरी तरह से लागू नहीं होता, जब तक वह लागू नहीं हो जाता. इसलिए, ऑप्टिमाइज़र को यह नहीं पता होता कि कौनसा कोड सुरक्षित तरीके से हटाया जा सकता है. ऐसा करने से, रनटाइम के दौरान रिफ़्लेक्शन की मदद से डाइनैमिक तौर पर इस्तेमाल किया जाने वाला कोड हट जाएगा. इसकी वजह से, उपयोगकर्ताओं के लिए ऐप्लिकेशन क्रैश हो सकता है.

कई आधुनिक लाइब्रेरी, रिफ़्लेक्शन के बजाय codegen का इस्तेमाल करती हैं. सामान्य एंट्री पॉइंट के लिए, KSP देखें. इसका इस्तेमाल Room, Dagger2 वगैरह करते हैं.

प्रतिबिंब कब ठीक है

अगर आपको रिफ़्लेक्शन का इस्तेमाल करना है, तो सिर्फ़ इनमें से किसी एक का इस्तेमाल करें:

  • टारगेट किए गए खास टाइप (इंटरफ़ेस लागू करने वाले खास लोग या सबक्लास)
  • किसी खास रनटाइम एनोटेशन का इस्तेमाल करने वाला कोड

इस तरह से रिफ़्लेक्शन का इस्तेमाल करने से, रनटाइम की लागत कम होती है. साथ ही, टारगेट किए गए उपभोक्ता के लिए, डेटा को सेव रखने के नियम लिखे जा सकते हैं.

रिफ़्लेक्शन का यह खास और टारगेट किया गया फ़ॉर्म, एक पैटर्न है. इसे Android फ़्रेमवर्क (उदाहरण के लिए, गतिविधियों, व्यू, और ड्रॉबल को फ़्लोरेट करते समय) और AndroidX लाइब्रेरी, दोनों में देखा जा सकता है. उदाहरण के लिए, WorkManager ListenableWorkers या RoomDatabases बनाते समय. इसके उलट, Gson को Android ऐप्लिकेशन में इस्तेमाल करना सही नहीं है.

उपभोक्ता के डेटा को सेव रखने के नियम लिखना

लाइब्रेरी को "उपभोक्ता" के लिए, डेटा को सेव रखने के नियमों को पैकेज करना चाहिए. ये नियम, ऐप्लिकेशन के लिए डेटा को सेव रखने के नियमों के जैसे ही फ़ॉर्मैट में होते हैं. इन नियमों को लाइब्रेरी आर्टफ़ैक्ट (एएआर या JAR) में बंडल किया जाता है. साथ ही, लाइब्रेरी का इस्तेमाल करने पर, Android ऐप्लिकेशन को ऑप्टिमाइज़ करने के दौरान ये नियम अपने-आप लागू हो जाते हैं.

एएआर लाइब्रेरी

किसी AAR लाइब्रेरी के लिए उपभोक्ता नियम जोड़ने के लिए, Android लाइब्रेरी मॉड्यूल की बिल्ड स्क्रिप्ट में consumerProguardFiles विकल्प का इस्तेमाल करें. ज़्यादा जानकारी के लिए, लाइब्रेरी मॉड्यूल बनाने के बारे में दिशा-निर्देश देखें.

Kotlin

android {
    defaultConfig {
        consumerProguardFiles("consumer-proguard-rules.pro")
    }
    ...
}

Groovy

android {
    defaultConfig {
        consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    ...
}

JAR लाइब्रेरी

JAR के तौर पर शिप की जाने वाली Kotlin/Java लाइब्रेरी के साथ नियमों को बंडल करने के लिए, अपनी नियम फ़ाइल को किसी भी फ़ाइल नाम के साथ, फ़ाइनल JAR की META-INF/proguard/ डायरेक्ट्री में डालें. उदाहरण के लिए, अगर आपका कोड <libraryroot>/src/main/kotlin में है, तो <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro पर उपभोक्ता के लिए बने नियमों की फ़ाइल डालें. इससे, नियम आपके आउटपुट JAR में सही जगह पर बंडल हो जाएंगे.

पुष्टि करें कि फ़ाइनल JAR बंडल, नियमों को सही तरीके से बंडल करता है. इसके लिए, देखें कि नियम META-INF/proguard डायरेक्ट्री में मौजूद हैं या नहीं.

अलग-अलग 'छोटा करने वाले टूल' के साथ काम करना (बेहतर)

खास टारगेट करने वाले किसी खास शंकर (R8 या ProGuard) के साथ-साथ, शंकर के खास वर्शन के लिए नियम बनाए जा सकते हैं. इससे आपकी लाइब्रेरी, नए वर्शन वाले प्रोजेक्ट में बेहतर तरीके से काम कर पाएगी. साथ ही, पुराने वर्शन वाले प्रोजेक्ट में मौजूदा नियमों का इस्तेमाल जारी रखा जा सकेगा.

टारगेट किए गए छोटे किए गए नियमों को तय करने के लिए, आपको उन्हें AAR या JAR लाइब्रेरी में कुछ खास जगहों पर शामिल करना होगा, जैसा कि यहां बताया गया है.

In an AAR library:
    consumer-proguard-rules.pro (legacy location)
    classes.jar
    └── META-INF
        └── com.android.tools (targeted shrink rules location)
            ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
            └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

In a JAR library:
    META-INF
    ├── proguard/<ProGuard-rules-file> (legacy location)
    └── com.android.tools (targeted shrink rules location)
        ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
        └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

इसका मतलब है कि टारगेट किए गए सिंक किए गए नियम, JAR की META-INF/com.android.tools डायरेक्ट्री में या AAR की classes.jar में मौजूद META-INF/com.android.tools डायरेक्ट्री में सेव किए जाते हैं.

उस डायरेक्ट्री में, r8-from-<X>-upto-<Y> या proguard-from-<X>-upto-<Y> के फ़ॉर्मैट में नाम वाली कई डायरेक्ट्री हो सकती हैं. इससे यह पता चलता है कि डायरेक्ट्री में मौजूद नियम, किस श्रिंकर के किस वर्शन के लिए लिखे गए हैं. ध्यान दें कि -from-<X> और -upto-<Y> वाले हिस्से ज़रूरी नहीं हैं. <Y> वर्शन खास है. साथ ही, वर्शन की रेंज लगातार होनी चाहिए.

उदाहरण के लिए, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 और r8-from-8.2.0, टारगेट किए गए शंर्क नियमों का मान्य सेट बनाते हैं. r8-from-8.0.0-upto-8.2.0 डायरेक्ट्री में दिए गए नियमों का इस्तेमाल, R8 में 8.0.0 से लेकर 8.2.0 तक के वर्शन में किया जाएगा. हालांकि, 8.2.0 वर्शन में इन नियमों का इस्तेमाल नहीं किया जाएगा.

इस जानकारी के आधार पर, Android Gradle प्लग-इन, मैच होने वाली R8 डायरेक्ट्री से नियम चुनता है. अगर किसी लाइब्रेरी में, टारगेट किए गए छोटे किए गए वर्शन के नियमों के बारे में नहीं बताया गया है, तो Android Gradle प्लग इन, लेगसी जगहों (एएआर के लिए proguard.txt या JAR के लिए META-INF/proguard/<ProGuard-rules-file>) से नियम चुनेगा.