लाइब्रेरी चुनने में सावधानी बरतना

ऐप्लिकेशन ऑप्टिमाइज़ेशन की सुविधा चालू करने के लिए, आपको ऐसी लाइब्रेरी इस्तेमाल करनी होंगी जो Android ऑप्टिमाइज़ेशन के साथ काम करती हों. अगर किसी लाइब्रेरी को Android ऑप्टिमाइज़ेशन के लिए कॉन्फ़िगर नहीं किया गया है, तो हो सकता है कि वह Android ऐप्लिकेशन के लिए सही न हो. उदाहरण के लिए, अगर वह Keep से जुड़ी शर्तों को बंडल किए बिना reflection का इस्तेमाल करती है. इस पेज पर बताया गया है कि कुछ लाइब्रेरी, ऐप्लिकेशन ऑप्टिमाइज़ेशन के लिए बेहतर क्यों होती हैं. साथ ही, आपको चुनने में मदद करने के लिए सामान्य सुझाव दिए गए हैं.

रिफ़्लेक्शन के बजाय कोड जनरेशन को प्राथमिकता दें

आम तौर पर, आपको ऐसी लाइब्रेरी चुननी चाहिए जो रिफ़्लेक्शन के बजाय कोड जनरेशन (codegen) का इस्तेमाल करती हैं. कोड जनरेशन की मदद से, ऑप्टिमाइज़र यह आसानी से तय कर सकता है कि रनटाइम में कौनसा कोड इस्तेमाल किया जाता है और कौनसा कोड हटाया जा सकता है. यह पता लगाना मुश्किल हो सकता है कि कोई लाइब्रेरी कोड जनरेशन या रिफ़्लेक्शन का इस्तेमाल करती है या नहीं. हालांकि, इसके कुछ संकेत होते हैं. मदद पाने के लिए, सलाह देखें.

कोड जनरेशन बनाम रिफ़्लेक्शन के बारे में ज़्यादा जानने के लिए, लाइब्रेरी के लेखकों के लिए ऑप्टिमाइज़ेशन देखें.

लाइब्रेरी चुनते समय सामान्य सलाह

इन सुझावों का इस्तेमाल करके, यह पक्का करें कि आपकी लाइब्रेरी, ऐप्लिकेशन ऑप्टिमाइज़ेशन के साथ काम करती हैं.

ऑप्टिमाइज़ेशन से जुड़ी समस्याएं देखना

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

  • AndroidX लाइब्रेरी और Hilt जैसी लाइब्रेरी, ऐप्लिकेशन को ऑप्टिमाइज़ करने के लिए बेहतर तरीके से काम करती हैं. ऐसा इसलिए, क्योंकि ये रिफ़्लेक्शन के बजाय कोडजन का इस्तेमाल करती हैं. जब वे रिफ़्लेक्शन का इस्तेमाल करते हैं, तो वे सिर्फ़ ज़रूरी कोड को बनाए रखने के लिए, कम से कम कीप नियमों का इस्तेमाल करते हैं.
  • सीरियलाइज़ेशन लाइब्रेरी, ऑब्जेक्ट को इंस्टैंटिएट या सीरियलाइज़ करते समय, अक्सर रिफ़्लेक्शन का इस्तेमाल करती हैं, ताकि बॉयलरप्लेट कोड से बचा जा सके. रिफ़्लेक्शन पर आधारित तरीकों (जैसे, JSON के लिए Gson) के बजाय, ऐसी लाइब्रेरी ढूंढें जो इन समस्याओं से बचने के लिए कोड जनरेशन का इस्तेमाल करती हैं. उदाहरण के लिए, इसके बजाय Kotlin Serialization का इस्तेमाल करें.
  • अगर हो सके, तो उन लाइब्रेरी का इस्तेमाल न करें जिनमें पैकेज के हिसाब से डेटा सुरक्षित रखने के नियम शामिल हों. पैकेज के लिए तय किए गए नियमों के तहत, डेटा को सुरक्षित रखने से गड़बड़ियों को ठीक करने में मदद मिल सकती है. हालांकि, डेटा को सुरक्षित रखने के लिए तय किए गए नियमों को बेहतर बनाया जाना चाहिए, ताकि सिर्फ़ ज़रूरी कोड को सुरक्षित रखा जा सके. ज़्यादा जानकारी के लिए, ऑप्टिमाइज़ेशन को धीरे-धीरे लागू करना लेख पढ़ें.
  • लाइब्रेरी को, दस्तावेज़ से कीप नियमों को कॉपी करके, आपके प्रोजेक्ट की किसी फ़ाइल में चिपकाने की ज़रूरत नहीं होनी चाहिए. खास तौर पर, पैकेज-वाइड कीप नियमों को कॉपी करके चिपकाने की ज़रूरत नहीं होनी चाहिए. इन नियमों की वजह से, ऐप्लिकेशन डेवलपर को लंबे समय तक रखरखाव से जुड़ी समस्याएं होती हैं. साथ ही, समय के साथ इन्हें ऑप्टिमाइज़ करना और बदलना मुश्किल होता है.

नई लाइब्रेरी जोड़ने के बाद ऑप्टिमाइज़ेशन की सुविधा चालू करना

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

नियमों को जोड़ा जा सकता है

ध्यान रखें कि निजी डेटा के रखरखाव के नियम, एक-दूसरे से जुड़े होते हैं. इसका मतलब है कि लाइब्रेरी डिपेंडेंसी में शामिल कुछ नियमों को हटाया नहीं जा सकता. साथ ही, ये आपके ऐप्लिकेशन के अन्य हिस्सों के कंपाइलेशन पर असर डाल सकते हैं. उदाहरण के लिए, अगर किसी लाइब्रेरी में कोड ऑप्टिमाइज़ेशन को बंद करने का नियम शामिल है, तो वह नियम आपके पूरे प्रोजेक्ट के लिए ऑप्टिमाइज़ेशन को बंद कर देता है.

रिफ़्लेक्शन (ऐडवांस) के इस्तेमाल की जांच करना

लाइब्रेरी के कोड की जांच करके, यह पता लगाया जा सकता है कि वह रिफ़्लेक्शन का इस्तेमाल करती है या नहीं. अगर लाइब्रेरी रिफ़्लेक्शन का इस्तेमाल करती है, तो पक्का करें कि वह Keep से जुड़े नियम उपलब्ध कराती हो. अगर कोई लाइब्रेरी ये काम करती है, तो हो सकता है कि वह रिफ़्लेक्शन का इस्तेमाल कर रही हो:

  • kotlin.reflect या java.lang.reflect पैकेज की क्लास या तरीकों का इस्तेमाल करता हो
  • Class.forName या classLoader.getClass फ़ंक्शन का इस्तेमाल करता है
  • यह रनटाइम के दौरान एनोटेशन पढ़ता है. उदाहरण के लिए, अगर यह val value = myClass.getAnnotation() या val value = myMethod.getAnnotation() का इस्तेमाल करके एनोटेशन वैल्यू सेव करता है और फिर value के साथ कुछ करता है
  • यह तरीके के नाम को स्ट्रिंग के तौर पर इस्तेमाल करके, तरीकों को कॉल करता है. उदाहरण के लिए:

    // Calls the private `processData` API with reflection
    myObject.javaClass.getMethod("processData", DataType::class.java)
    ?.invoke(myObject, data)
    

खराब कीप नियमों को फ़िल्टर करना (ऐडवांस)

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

// If you're using AGP 8.4 and higher
buildTypes {
    release {
        optimization.keepRules {
          it.ignoreFrom("com.somelibrary:somelibrary")
        }
    }
}

// If you're using AGP 7.3-8.3
buildTypes {
    release {
        optimization.keepRules {
          it.ignoreExternalDependencies("com.somelibrary:somelibrary")
        }
    }
}

केस स्टडी: ऑप्टिमाइज़ेशन के साथ Gson क्यों काम नहीं करता

Gson, एक सीरियलाइज़ेशन लाइब्रेरी है. यह अक्सर ऐप्लिकेशन ऑप्टिमाइज़ेशन में समस्याएं पैदा करती है, क्योंकि यह रिफ़्लेक्शन का ज़्यादा इस्तेमाल करती है. नीचे दिए गए कोड स्निपेट में दिखाया गया है कि Gson का इस्तेमाल आम तौर पर कैसे किया जाता है. इससे रनटाइम के दौरान आसानी से क्रैश हो सकता है. ध्यान दें कि User ऑब्जेक्ट की सूची पाने के लिए Gson का इस्तेमाल करते समय, कंस्ट्रक्टर को कॉल नहीं किया जाता या fromJson() फ़ंक्शन को फ़ैक्ट्री पास नहीं की जाती. अगर ऐप्लिकेशन में तय की गई क्लास को इन दोनों में से किसी भी तरीके से नहीं बनाया जा रहा है या इस्तेमाल नहीं किया जा रहा है, तो इसका मतलब है कि लाइब्रेरी, ओपन-एंडेड रिफ़्लेक्शन का इस्तेमाल कर रही है:

  • लाइब्रेरी, स्टैंडर्ड इंटरफ़ेस या क्लास को लागू करने वाली ऐप्लिकेशन क्लास
  • कोड जनरेशन प्लगिन, जैसे कि KSP
class User(val name: String)
class UserList(val users: List<User>)

// This code runs in debug mode, but crashes when optimizations are enabled
Gson().fromJson("""[{"name":"myname"}]""", User::class.java).toString()

जब R8 इस कोड का विश्लेषण करता है और उसे कहीं भी UserList या User इंस्टैंशिएट नहीं दिखता है, तो वह फ़ील्ड का नाम बदल सकता है या ऐसे कंस्ट्रक्टर हटा सकता है जिनका इस्तेमाल नहीं किया जा रहा है. इससे आपका ऐप्लिकेशन क्रैश हो सकता है. अगर इसी तरह से किसी दूसरी लाइब्रेरी का इस्तेमाल किया जा रहा है, तो आपको यह देखना चाहिए कि वे ऐप्लिकेशन ऑप्टिमाइज़ेशन में रुकावट न डालें. अगर वे रुकावट डालती हैं, तो उनका इस्तेमाल न करें.

ध्यान दें कि Room और Hilt, दोनों ही ऐप्लिकेशन के हिसाब से टाइप बनाते हैं. हालांकि, रिफ़्लेक्शन की ज़रूरत से बचने के लिए, ये कोड जनरेशन का इस्तेमाल करते हैं.