ऐप्लिकेशन ऑप्टिमाइज़ेशन की सुविधा चालू करने के लिए, आपको ऐसी लाइब्रेरी इस्तेमाल करनी होंगी जो Android ऑप्टिमाइज़ेशन के साथ काम करती हों. अगर किसी लाइब्रेरी को Android के हिसाब से ऑप्टिमाइज़ नहीं किया गया है, तो हो सकता है कि वह Android ऐप्लिकेशन के लिए सही न हो. उदाहरण के लिए, अगर वह लाइब्रेरी, Keep से जुड़े नियमों को बंडल किए बिना reflection का इस्तेमाल करती है. इस पेज पर बताया गया है कि कुछ लाइब्रेरी, ऐप्लिकेशन को ऑप्टिमाइज़ करने के लिए बेहतर क्यों होती हैं. साथ ही, आपको सही लाइब्रेरी चुनने में मदद करने के लिए सामान्य सुझाव दिए गए हैं.
लाइब्रेरी चुनते समय ध्यान रखने वाली सामान्य बातें
इन सुझावों का इस्तेमाल करके, यह पक्का करें कि आपकी लाइब्रेरी, ऐप्लिकेशन ऑप्टिमाइज़ेशन के साथ काम करती हैं.
रिफ़्लेक्शन के बजाय कोड जनरेशन को प्राथमिकता दें
ऐसी लाइब्रेरी चुनें जो रिफ़्लेक्शन के बजाय कोड जनरेशन (codegen) का इस्तेमाल करती हैं. कोड जनरेशन की मदद से ऑप्टिमाइज़र यह तय कर सकता है कि रनटाइम के दौरान कौनसा कोड इस्तेमाल किया जाता है और कौनसा कोड हटाया जा सकता है. यह पता लगाना मुश्किल हो सकता है कि कोई लाइब्रेरी कोडजन या रिफ़्लेक्शन का इस्तेमाल करती है या नहीं. हालांकि, इसके कुछ संकेत होते हैं. मदद पाने के लिए, सलाह देखें.
कोड जनरेशन बनाम रिफ़्लेक्शन के बारे में ज़्यादा जानने के लिए, लाइब्रेरी तैयार करने वालों के लिए ऑप्टिमाइज़ेशन लेख पढ़ें.
रिफ़्लेक्शन (ऐडवांस) के इस्तेमाल की जांच करना
किसी लाइब्रेरी के कोड की जांच करके, यह पता लगाया जा सकता है कि वह रिफ़्लेक्शन का इस्तेमाल करती है या नहीं. अगर लाइब्रेरी रिफ़्लेक्शन का इस्तेमाल करती है, तो देखें कि वह डेटा बनाए रखने के नियम लागू करती हो. अगर कोई लाइब्रेरी ये काम करती है, तो हो सकता है कि वह रिफ़्लेक्शन का इस्तेमाल करती हो:
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)
ऑप्टिमाइज़ेशन से जुड़ी समस्याएं देखना
नई लाइब्रेरी का इस्तेमाल करने से पहले, लाइब्रेरी के इश्यू ट्रैकर और ऑनलाइन चर्चाओं को देखें. इससे आपको यह पता चलेगा कि क्या लाइब्रेरी में, कोड छोटा करने या ऐप्लिकेशन ऑप्टिमाइज़ेशन को कॉन्फ़िगर करने से जुड़ी समस्याएं हैं. अगर ऐसा है, तो आपको उस लाइब्रेरी के विकल्पों को ढूंढना चाहिए. इन बातों का ध्यान रखें:
- AndroidX लाइब्रेरी और Hilt जैसी लाइब्रेरी, ऐप्लिकेशन को ऑप्टिमाइज़ करने के लिए बेहतर तरीके से काम करती हैं. इसकी वजह यह है कि ये ज़्यादातर रिफ़्लेक्शन के बजाय कोडजन का इस्तेमाल करती हैं. जब वे रिफ़्लेक्शन का इस्तेमाल करते हैं, तो वे सिर्फ़ ज़रूरी कोड को बनाए रखने के लिए, कम से कम नियमों का पालन करते हैं.
- सीरियलाइज़ेशन लाइब्रेरी, ऑब्जेक्ट को इंस्टैंटिएट या सीरियलाइज़ करते समय, अक्सर रिफ़्लेक्शन का इस्तेमाल करती हैं. इससे उन्हें बॉयलरप्लेट कोड से बचने में मदद मिलती है. रेफ़्लेक्शन पर आधारित तरीकों (जैसे, JSON के लिए Gson) के बजाय, ऐसी लाइब्रेरी खोजें जो इन समस्याओं से बचने के लिए कोड जनरेशन का इस्तेमाल करती हैं. उदाहरण के लिए, Kotlin Serialization{:.external} या कोड जनरेशन के साथ Moshi का इस्तेमाल करें.
- अगर हो सके, तो ऐसी लाइब्रेरी का इस्तेमाल न करें जिनमें पैकेज के हिसाब से डेटा सुरक्षित रखने के नियम शामिल हों. पैकेज के लिए तय किए गए कीप नियमों से गड़बड़ियों को ठीक करने में मदद मिल सकती है. हालांकि, ब्रॉड कीप नियमों को आखिर में बेहतर बनाया जाना चाहिए, ताकि सिर्फ़ ज़रूरी कोड को रखा जा सके. ज़्यादा जानकारी के लिए, ऑप्टिमाइज़ेशन को धीरे-धीरे लागू करना लेख पढ़ें.
- तीसरे पक्ष की लाइब्रेरी का इस्तेमाल करने वाले ऐप्लिकेशन को पब्लिश करने से पहले, R8 कॉन्फ़िगरेशन ऐनलिसिस टूल का इस्तेमाल करके, लाइब्रेरी के कीप नियमों की जांच करें. रिपोर्ट की समीक्षा करके, यह पुष्टि की जा सकती है कि लाइब्रेरी के कीप नियमों का दायरा बहुत बड़ा तो नहीं है. ऐसा होने पर, R8 आपके कोडबेस पर ज़रूरी ऑप्टिमाइज़ेशन नहीं कर पाता. इस जांच से यह पक्का होता है कि चुनी गई लाइब्रेरी, आपके ऐप्लिकेशन की परफ़ॉर्मेंस के लक्ष्यों के मुताबिक हैं. साथ ही, इनसे कॉन्फ़िगरेशन में ज़रूरत से ज़्यादा डेटा नहीं जुड़ता.
- लाइब्रेरी में, आपको दस्तावेज़ से कीप नियमों को कॉपी करके, अपने प्रोजेक्ट की किसी फ़ाइल में चिपकाने की ज़रूरत नहीं होनी चाहिए. खास तौर पर, पैकेज-वाइड कीप नियमों के लिए. इन नियमों की वजह से, ऐप्लिकेशन डेवलपर को लंबे समय तक रखरखाव से जुड़ी समस्याओं का सामना करना पड़ता है. साथ ही, समय के साथ इन्हें ऑप्टिमाइज़ करना और बदलना मुश्किल होता है.
नई लाइब्रेरी जोड़ने के बाद ऑप्टिमाइज़ेशन की सुविधा चालू करना
नई लाइब्रेरी जोड़ने के बाद, ऑप्टिमाइज़ेशन की सुविधा चालू करें और देखें कि कोई गड़बड़ी तो नहीं है. अगर कोई गड़बड़ी है, तो उस लाइब्रेरी के विकल्प ढूंढें या नियमों को लागू रखें. अगर कोई लाइब्रेरी ऑप्टिमाइज़ेशन के साथ काम नहीं करती है, तो उस लाइब्रेरी के साथ गड़बड़ी की शिकायत करें.
खराब कीप नियमों को फ़िल्टर करना (ऐडवांस)
निजी डेटा के रखरखाव के नियम, एक-दूसरे से जुड़े होते हैं. इसका मतलब है कि लाइब्रेरी डिपेंडेंसी में शामिल कुछ नियमों को हटाया नहीं जा सकता. साथ ही, ये नियम आपके ऐप्लिकेशन के अन्य हिस्सों के कंपाइलेशन पर असर डाल सकते हैं. उदाहरण के लिए, अगर किसी लाइब्रेरी में कोड ऑप्टिमाइज़ेशन को बंद करने का नियम शामिल है, तो यह नियम आपके पूरे प्रोजेक्ट के लिए ऑप्टिमाइज़ेशन को बंद कर देता है.
आपको ऐसी लाइब्रेरी इस्तेमाल नहीं करनी चाहिए जिनमें कोड को बनाए रखने के नियम लागू होते हैं. ऐसा इसलिए, क्योंकि इन नियमों के तहत ऐसे कोड को भी बनाए रखा जाता है जिसे हटा दिया जाना चाहिए. हालांकि, अगर आपको इनका इस्तेमाल करना ही है, तो यहां दिए गए कोड में दिखाए गए तरीके से नियमों को फ़िल्टर किया जा सकता है:
// 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()
Gson पर R8 के काम करने के तरीके को समझने के लिए, Gson के उपभोक्ता नियम देखें. जब R8 इस कोड का विश्लेषण करता है और उसे कहीं भी UserList या User इंस्टैंशिएट नहीं दिखता है, तो वह फ़ील्ड का नाम बदल सकता है या ऐसे कंस्ट्रक्टर हटा सकता है जिनका इस्तेमाल नहीं किया जा रहा है. इससे आपका ऐप्लिकेशन क्रैश हो सकता है. अगर इसी तरह से किसी दूसरी लाइब्रेरी का इस्तेमाल किया जा रहा है, तो आपको यह देखना चाहिए कि वे ऐप्लिकेशन ऑप्टिमाइज़ेशन में रुकावट न डालें. अगर वे रुकावट डालती हैं, तो उनका इस्तेमाल न करें.
Gson के उपभोक्ता नियमों के साथ काम करने वाली क्लास तय करने के लिए, इस स्निपेट का इस्तेमाल रेफ़रंस के तौर पर करें:
class User(@com.google.gson.annotations.SerializedName("name") val name: String)
class UserList(@com.google.gson.annotations.SerializedName("users") val users: List<User>)
ध्यान दें कि Room, Hilt, और Moshi with codegen, ऐप्लिकेशन के हिसाब से टाइप बनाते हैं. हालांकि, ये रिफ़्लेक्शन की ज़रूरत से बचने के लिए codegen का इस्तेमाल करते हैं.