2017-06-12 16 views
346

में संकलन एंड्रॉयड स्टूडियो 3.0 करने के लिए अद्यतन करने और एक नई परियोजना बनाने के बाद, मैंने देखा build.gradle में compile के बजाय नई निर्भरता को जोड़ने के लिए है नहीं है implementation और बजाय testCompile एक नया तरीका है कि वहाँ testImplementationक्या कार्यान्वयन के बीच का अंतर है और Gradle

उदाहरण:

implementation 'com.android.support:appcompat-v7:25.0.0' 
testImplementation 'junit:junit:4.12' 

compile 'com.android.support:appcompat-v7:25.0.0' 
testCompile 'junit:junit:4.12' 

उन दोनों के बीच क्या अंतर है और मैं क्या का उपयोग करना चाहिए के बजाय?

उत्तर

496

यह तोड़ने परिवर्तन Gradle के साथ आने वाले में से एक है: 3.0 है कि गूगल announced at IO17 Gradle: 3.0

compile विन्यास now deprecated है और द्वारा implementation या api

gradle docs से प्रतिस्थापित किया जाना चाहिए:

dependencies { 
    api 'commons-httpclient:commons-httpclient:3.1' 
    implementation 'org.apache.commons:commons-lang3:3.5' 
} 

api में प्रदर्शित निर्भरता कॉन्फ़िगरेशन लाइब्रेरी के उपभोक्ताओं के लिए पारस्परिक रूप से उजागर होगा, और ऐसे में उपभोक्ताओं के संकलन वर्गीकरण पर दिखाई देंगे।

निर्भरता implementation विन्यास में पाया, दूसरे हाथ पर, उपभोक्ताओं के संपर्क में नहीं किया जाएगा, और इसलिए उपभोक्ताओं की संकलन classpath में लीक नहीं। यह कई लाभ के साथ आता है:

  • निर्भरता अब और उपभोक्ताओं के संकलन classpath में रिसाव नहीं है, ताकि आप कभी गलती से एक सकर्मक पर निर्भरता
  • तेजी से संकलन कम classpath आकार
  • कम recompilations करने के लिए धन्यवाद निर्भर करेगा जब कार्यान्वयन निर्भरता बदलती है: उपभोक्ताओं को
  • क्लीनर प्रकाशन: जब नए मेवेन-प्रकाशित प्लगइन के संयोजन के साथ प्रयोग किया जाता है, तो जावा लाइब्रेरी पीओएम फाइलें उत्पन्न करती हैं जो कॉम के लिए आवश्यक चीज़ों के बीच बिल्कुल अंतर करती है लाइब्रेरी के विरुद्ध ढेर और रनटाइम पर लाइब्रेरी का उपयोग करने के लिए क्या आवश्यक है (अन्य शब्दों में, लाइब्रेरी को संकलित करने के लिए क्या आवश्यक है और लाइब्रेरी के विरुद्ध संकलन करने के लिए की आवश्यकता नहीं है)।

संकलन विन्यास अभी भी मौजूद है लेकिन इसका उपयोग नहीं किया जाना चाहिए क्योंकि यह गारंटी प्रदान नहीं करेगा कि एपीआई और कार्यान्वयन विन्यास प्रदान करता है।


tl; डॉ

बस की जगह:

साथ implementation
  • testCompile साथ testImplementation
    • androidTestCompile साथ साथ androidTestImplementation
  • +50

    "उपभोक्ता" कौन हैं? – Suragch

    +11

    उपभोक्ता लाइब्रेरी का उपयोग कर मॉड्यूल है। एंड्रॉइड के मामले में, यह एंड्रॉइड एप्लिकेशन है। मुझे लगता है कि यह स्पष्ट है और मुझे यकीन नहीं है कि यह वही है जो आप पूछ रहे हैं। – humazed

    +9

    यही वह है जो मुझे भी पसंद आया। लेकिन अगर मैं पुस्तकालय बना रहा हूं, तो निश्चित रूप से मैं चाहता हूं कि इसकी एपीआई ऐप के संपर्क में आ जाए। अन्यथा, ऐप डेवलपर मेरी लाइब्रेरी का उपयोग कैसे करेगा? यही कारण है कि मुझे निर्भरता को छिपाने के 'कार्यान्वयन' का अर्थ नहीं मिलता है। क्या मेरा प्रश्न समझ में आता है? – Suragch

    33

    Compile विन्यास पदावनत किया गया था और implementation या api द्वारा प्रतिस्थापित किया जाना चाहिए।

    आप https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation पर दस्तावेज़ पढ़ सकते हैं।

    being-

    मानक जावा प्लगइन और जावा लाइब्रेरी प्लगइन के बीच मुख्य अंतर संक्षिप्त बात यह है कि बाद के एक API उपभोक्ताओं के संपर्क में की अवधारणा का परिचय है। एक लाइब्रेरी एक जावा घटक है जिसका मतलब अन्य घटकों द्वारा खपत किया गया है। मल्टी-प्रोजेक्ट बिल्ड में यह एक बहुत ही आम उपयोग केस है, लेकिन जैसे ही आपके पास बाहरी निर्भरताएं हैं।

    प्लगइन दो कॉन्फ़िगरेशन का खुलासा करता है जिसका उपयोग निर्भरताओं को घोषित करने के लिए किया जा सकता है: एपीआई और कार्यान्वयन। एपीआई कॉन्फ़िगरेशन लाइब्रेरी एपीआई, द्वारा निर्यात की गई निर्भरताओं की घोषणा करने के लिए प्रयुक्त होता है जबकि कार्यान्वयन कॉन्फ़िगरेशन का उपयोग निर्भरताओं को घोषित करने के लिए किया जाना चाहिए जो घटक के लिए आंतरिक हैं।

    आगे की व्याख्या के लिए इस छवि का संदर्भ लें। Brief explanation

    18

    संक्षिप्त समाधान:

    बेहतर दृष्टिकोण implementation निर्भरता के साथ सभी compile निर्भरता को बदलने के लिए है। और केवल जहां आप मॉड्यूल के इंटरफ़ेस को रिसाव करते हैं, आपको api का उपयोग करना चाहिए। इससे बहुत कम पुनर्मूल्यांकन हो सकता है।

    dependencies { 
         implementation fileTree(dir: 'libs', include: ['*.jar']) 
    
         implementation 'com.android.support:appcompat-v7:25.4.0' 
         implementation 'com.android.support.constraint:constraint-layout:1.0.2' 
         // … 
    
         testImplementation 'junit:junit:4.12' 
         androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { 
          exclude group: 'com.android.support', module: 'support-annotations' 
         }) 
    } 
    

    के बारे में बताएं अधिक:

    से पहले एंड्रॉयड Gradle प्लगइन 3.0: हम एक बड़ी समस्या जो एक कोड परिवर्तन का कारण बनता है सभी मॉड्यूल कंपाइल किया जा रहा है था। इसके लिए मूल कारण यह है कि ग्रैडल नहीं जानता कि क्या आप किसी मॉड्यूल के इंटरफ़ेस को किसी अन्य के माध्यम से रिसाव करते हैं या नहीं।

    Android Gradle प्लगइन 3 के बाद।0: नवीनतम एंड्रॉइड ग्रैडल प्लगइन के लिए अब आपको स्पष्ट रूप से परिभाषित करने की आवश्यकता है कि क्या आप मॉड्यूल के इंटरफ़ेस को रिसाव करते हैं। इसके आधार पर यह सही विकल्प चुन सकता है कि उसे क्या करना चाहिए।

    के रूप में इस तरह के compile निर्भरता पदावनत किया गया है और दो नए लोगों द्वारा लाए गए:

    • api: आप अपने खुद के इंटरफेस के माध्यम से इस मॉड्यूल के इंटरफ़ेस लीक, पुराने compile निर्भरता

      के रूप में बिल्कुल एक ही अर्थ
    • implementation: यदि आप केवल इस मॉड्यूल आंतरिक रूप से उपयोग करें और अपनी इंटरफेस के माध्यम से यह लीक नहीं करता

    तो अब आप मॉड्यूल को फिर से कंपाइल करने के लिए ग्रैडल को स्पष्ट रूप से बता सकते हैं यदि किसी मॉड्यूल का इंटरफ़ेस बदलता है या नहीं।

    Jeroen Mols ब्लॉग के सौजन्य

    26

    इस उत्तर एक परियोजना पर implementation, api, और compile के बीच अंतर का प्रदर्शन करेंगे।

    • एप्लिकेशन myandroidlibrary (Android एप्लिकेशन)
    • myandroidlibrary (एक Android पुस्तकालय)
    • myjavalibrary (एक जावा पुस्तकालय)

    app है: मान लीजिए कि मैं तीन Gradle मॉड्यूल के साथ एक परियोजना करते हैं निर्भरता के रूप में। myandroidlibrary में myjavalibrary निर्भरता के रूप में है।

    एप्लिकेशन -> myandroidlibrary -> myjavalibrary

    myjavalibrary है एक MySecret वर्ग

    public class MySecret { 
    
        public static String getSecret() { 
         return "Money"; 
        } 
    } 
    

    myandroidlibraryMyAndroidComponent वर्ग कि MySecret वर्ग से मूल्य में हेरफेर है।

    public class MyAndroidComponent { 
    
        private static String component = MySecret.getSecret(); 
    
        public static String getComponent() { 
         return "My component: " + component; 
        }  
    } 
    

    अन्त में, app केवल से myandroidlibrary

    TextView tvHelloWorld = findViewById(R.id.tv_hello_world); 
    tvHelloWorld.setText(MyAndroidComponent.getComponent()); 
    

    अब मूल्य पर रुचि है, के app build.gradle पर निर्भरता के बारे में बात करते हैं। यह बहुत सरल और सहज है।

    dependencies { 
        implementation project(':myandroidlibrary')  
    } 
    

    आपको क्या लगता myandroidlibrary build.gradle दिखेगा चाहिए? हम तीन विकल्प हैं:

    dependencies { 
        // Option #1 
        implementation project(':myjavalibrary') 
        // Option #2 
        compile project(':myjavalibrary')  
        // Option #3 
        api project(':myjavalibrary')   
    } 
    

    उन दोनों के बीच क्या अंतर है और मैं क्या का उपयोग करना चाहिए?

    संकलित करें और एपीआई

    आप compile और api उपयोग कर रहे हैं। हमारा एंड्रॉइड एप्लिकेशन अब myandroidcomponent निर्भरता तक पहुंचने में सक्षम है, जो MySecret वर्ग है।

    TextView textView = findViewById(R.id.text_view); 
    textView.setText(MyAndroidComponent.getComponent()); 
    // You can access MySecret 
    textView.setText(MySecret.getSecret()); 
    

    कार्यान्वयन

    आप implementation विन्यास का उपयोग कर रहे हैं, तो MySecret संपर्क में नहीं है।

    TextView textView = findViewById(R.id.text_view); 
    textView.setText(MyAndroidComponent.getComponent()); 
    // You can NOT access MySecret 
    textView.setText(MySecret.getSecret()); // Won't even compile 
    

    तो, आपको कौन सी कॉन्फ़िगरेशन चुनना चाहिए? यह वास्तव में आपकी आवश्यकता पर निर्भर करता है।

    यदि आप निर्भरता का पर्दाफाश करना चाहते हैं तो api या compile का उपयोग करें, यदि आप निर्भरता का खुलासा नहीं करना चाहते हैं (अपना आंतरिक मॉड्यूल छुपाएं) तो implementation का उपयोग करें।

    यह केवल ग्रैडल कॉन्फ़िगरेशन का एक सारांश है, Table 49.1. Java Library plugin - configurations used to declare dependencies इस बारे में अधिक विस्तृत स्पष्टीकरण है।

    हैप्पी एक्सप्लोरिंग

    संबंधित मुद्दे