ऐप्लिकेशन ऑप्टिमाइज़ेशन की सुविधा चालू करने के लिए, आपको ऐसी लाइब्रेरी इस्तेमाल करनी होंगी जो 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 या कोड जनरेशन के साथ Moshi का इस्तेमाल करें.
- अगर हो सके, तो ऐसी लाइब्रेरी का इस्तेमाल न करें जिनमें पैकेज के हिसाब से डेटा सुरक्षित रखने के नियम शामिल हों. पूरे पैकेज के लिए कीप रूल का इस्तेमाल करके, गड़बड़ियों को ठीक किया जा सकता है. हालांकि, ब्रॉड कीप रूल को आखिर में बेहतर बनाया जाना चाहिए, ताकि सिर्फ़ ज़रूरी कोड को रखा जा सके. ज़्यादा जानकारी के लिए, ऑप्टिमाइज़ेशन को धीरे-धीरे लागू करना लेख पढ़ें.
- लाइब्रेरी को, दस्तावेज़ से कीप नियमों को कॉपी करके, आपके प्रोजेक्ट की किसी फ़ाइल में चिपकाने की ज़रूरत नहीं होनी चाहिए. खास तौर पर, पैकेज-वाइड कीप नियमों को. इन नियमों को लंबे समय तक बनाए रखना, ऐप्लिकेशन डेवलपर के लिए मुश्किल होता है. साथ ही, समय के साथ इन्हें ऑप्टिमाइज़ करना और बदलना भी मुश्किल होता है.
नई लाइब्रेरी जोड़ने के बाद ऑप्टिमाइज़ेशन की सुविधा चालू करना
नई लाइब्रेरी जोड़ने के बाद, ऑप्टिमाइज़ेशन की सुविधा चालू करें और देखें कि कोई गड़बड़ी तो नहीं है. अगर कोई गड़बड़ी है, तो उस लाइब्रेरी के विकल्पों को देखें या नियमों को बनाए रखें. अगर कोई लाइब्रेरी ऑप्टिमाइज़ेशन के साथ काम नहीं करती है, तो उस लाइब्रेरी के लिए गड़बड़ी की रिपोर्ट सबमिट करें.
खराब कीप नियमों को फ़िल्टर करना (ऐडवांस)
निजी डेटा के रखरखाव के नियम, जोड़े जा सकते हैं. इसका मतलब है कि लाइब्रेरी डिपेंडेंसी में शामिल कुछ नियमों को हटाया नहीं जा सकता. साथ ही, ये नियम आपके ऐप्लिकेशन के अन्य हिस्सों के कंपाइलेशन पर असर डाल सकते हैं. उदाहरण के लिए, अगर किसी लाइब्रेरी में कोड ऑप्टिमाइज़ेशन को बंद करने का नियम शामिल है, तो यह नियम आपके पूरे प्रोजेक्ट के लिए ऑप्टिमाइज़ेशन को बंद कर देता है.
आपको ऐसी लाइब्रेरी से बचना चाहिए जिनमें कोड को बनाए रखने के नियम हों. ऐसा इसलिए, क्योंकि इन नियमों के तहत ऐसे कोड को भी बनाए रखा जाता है जिसे हटा दिया जाना चाहिए. हालांकि, अगर आपको इनका इस्तेमाल करना ही है, तो यहां दिए गए कोड में दिखाए गए तरीके से नियमों को फ़िल्टर किया जा सकता है:
// 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 का इस्तेमाल करते हैं.