เมื่อเพิ่มการพึ่งพา คุณอาจพบปัญหาเกี่ยวกับการพึ่งพาที่จําเป็นสําหรับการพึ่งพาเดิม และการขัดแย้งกันระหว่างการพึ่งพาเวอร์ชันต่างๆ วิธีวิเคราะห์กราฟความเกี่ยวข้องและแก้ไขปัญหาที่พบบ่อยมีดังนี้
ดูคําแนะนําในการแก้ไขข้อผิดพลาดในการแก้ไขข้อกําหนดซึ่งเกี่ยวข้องกับตรรกะการสร้างที่กําหนดเองได้ที่กลยุทธ์การแก้ไขข้อกําหนดที่กำหนดเอง
ใหม่
พรอมต์ AIแก้ไขข้อผิดพลาดในการแก้ไขข้อขัดข้อง
ข้อความแจ้งนี้ขอความช่วยเหลือในการแก้ไขข้อขัดแย้งของ Dependency
เรียกใช้พรอมต์นี้ใน Android Studio โดยเปิด build.gradle ไว้
I'm getting the following error in my build: Conflict with dependency. Resolved versions for runtime classpath and compile classpath differ. What changes do I need to make to my dependencies to resolve this error.
ดูทรัพยากร Dependency ของโมดูล
ไลบรารีที่ขึ้นต่อกันโดยตรงบางรายการอาจมีการขึ้นต่อกันของตนเอง ความสัมพันธ์เหล่านี้เรียกว่าการพึ่งพาแบบทรานซิทีฟ Gradle จะรวบรวมและเพิ่มข้อกำหนดที่ไม่เกี่ยวข้องกันแต่ละรายการให้คุณโดยอัตโนมัติแทนที่จะให้คุณประกาศด้วยตนเอง ปลั๊กอิน Android สำหรับ Gradle มีงานที่แสดงรายการของข้อกําหนดซึ่ง Gradle แก้ปัญหาสําหรับโมดูลหนึ่งๆ
รายงานจะจัดกลุ่มรายการที่ต้องใช้ตามตัวแปรการสร้าง ชุดแหล่งที่มาของการทดสอบ และเส้นทางคลาสสําหรับแต่ละโมดูลด้วย ต่อไปนี้เป็นตัวอย่างรายงานสำหรับรันไทม์ของโมดูลแอป เส้นทางของคลาสของตัวแปรบิลด์แก้ไขข้อบกพร่อง และเส้นทางของคลาสคอมไพล์ของชุดแหล่งที่มาทดสอบที่มีเครื่องมือวัด
debugRuntimeClasspath - Dependencies for runtime/packaging
+--- :mylibrary (variant: debug)
+--- com.google.android.material:material:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.2@aar
+--- androidx.constraintlayout:constraintlayout:1.1.3@aar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
...
debugAndroidTest
debugAndroidTestCompileClasspath - Dependencies for compilation
+--- androidx.test.ext:junit:1.1.0@aar
+--- androidx.test.espresso:espresso-core:3.1.1@aar
+--- androidx.test:runner:1.1.1@aar
+--- junit:junit:4.12@jar
...
หากต้องการเรียกใช้งาน ให้ทําตามขั้นตอนต่อไปนี้
- เลือกดู > หน้าต่างเครื่องมือ > Gradle (หรือคลิก Gradle ในแถบหน้าต่างเครื่องมือ)
- ขยาย AppName > Tasks > android และดับเบิลคลิก androidDependencies หลังจาก Gradle ดำเนินการแล้ว หน้าต่างเรียกใช้จะเปิดขึ้นเพื่อแสดงผลลัพธ์
ดูข้อมูลเพิ่มเติมเกี่ยวกับการจัดการทรัพยากรใน Gradle ได้ที่ข้อมูลเบื้องต้นเกี่ยวกับการจัดการทรัพยากรในคู่มือผู้ใช้ Gradle
ยกเว้น Dependency แบบทรานซิทีฟ
เมื่อแอปมีขอบเขตมากขึ้น ก็อาจมี Dependency หลายรายการ ซึ่งรวมถึง Dependency โดยตรงและ Dependency แบบทรานซิทีฟ (ไลบรารีที่แอปของคุณนําเข้าขึ้นต่อกัน)
หากต้องการยกเว้นการพึ่งพาแบบเปลี่ยนผ่านที่คุณไม่ต้องการอีกต่อไป ให้ใช้คีย์เวิร์ด exclude
ตามที่ระบุไว้ด้านล่าง
Kotlin
dependencies { implementation("some-library") { exclude(group = "com.example.imgtools", module = "native") } }
Groovy
dependencies { implementation('some-library') { exclude group: 'com.example.imgtools', module: 'native' } }
ยกเว้นการพึ่งพาแบบทรานซิทีฟจากการกําหนดค่าการทดสอบ
หากต้องการยกเว้นการพึ่งพาแบบเปลี่ยนผ่านบางอย่างออกจากการทดสอบ ตัวอย่างโค้ดที่แสดงด้านบนอาจไม่ทำงานตามที่คาดไว้ นั่นเป็นเพราะการกำหนดค่าการทดสอบ (เช่น androidTestImplementation
) ขยายการกำหนดค่าของimplementation
โมดูล กล่าวคือ ไฟล์ดังกล่าวจะมีimplementation
dependency เสมอเมื่อ Gradle แก้ปัญหาการกำหนดค่า
ดังนั้น หากต้องการยกเว้นการพึ่งพาแบบทรานซิทีฟจากการทดสอบ คุณต้องดำเนินการดังกล่าว ณ เวลาดำเนินการดังที่แสดงด้านล่าง
Kotlin
android.testVariants.all { compileConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp") runtimeConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp") }
Groovy
android.testVariants.all { variant -> variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp' variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp' }
หมายเหตุ: คุณยังคงใช้คีย์เวิร์ด exclude
ในบล็อก dependencies ได้ตามที่แสดงในตัวอย่างโค้ดต้นฉบับจากส่วนยกเว้น dependencies แบบทรานซิทีฟ เพื่อละเว้น dependencies แบบทรานซิทีฟที่ใช้กับการกําหนดค่าการทดสอบโดยเฉพาะและไม่รวมอยู่ในการกําหนดค่าอื่นๆ
แก้ไขข้อผิดพลาดในการแก้ไขข้อขัดข้อง
เมื่อคุณเพิ่มทรัพยากร Dependency หลายรายการลงในโปรเจ็กต์แอป ทรัพยากร Dependency โดยตรงและแบบสื่อกลางเหล่านั้นอาจขัดแย้งกัน ปลั๊กอิน Android Gradle จะพยายามแก้ไขข้อขัดแย้งเหล่านี้อย่างราบรื่น แต่ข้อขัดแย้งบางอย่างอาจทำให้เกิดข้อผิดพลาดเกี่ยวกับเวลาคอมไพล์หรือรันไทม์
เพื่อช่วยคุณตรวจสอบว่า Dependency ใดทำให้เกิดข้อผิดพลาด ให้ตรวจสอบแผนภูมิ Dependency ของแอปและมองหา Dependency ที่ปรากฏมากกว่า 1 ครั้งหรือมีเวอร์ชันที่ขัดแย้งกัน
หากระบุการพึ่งพาที่ซ้ำกันไม่ง่ายนัก ให้ลองใช้ UI ของ Android Studio เพื่อค้นหาการพึ่งพาที่มีคลาสที่ซ้ำกัน ดังนี้
- เลือกไปยังส่วนต่างๆ > ชั้นเรียนจากแถบเมนู
- ในกล่องโต้ตอบการค้นหาแบบป๊อปอัป ให้เลือกช่องข้างรวมรายการที่ไม่ใช่โปรเจ็กต์
- พิมพ์ชื่อคลาสที่ปรากฏในข้อผิดพลาดของบิลด์
- ตรวจสอบผลลัพธ์เพื่อหา Dependency ที่มีคลาส
ส่วนต่อไปนี้จะอธิบายข้อผิดพลาดในการแก้ไขข้อกําหนดเบื้องต้นประเภทต่างๆ ที่คุณอาจพบและวิธีแก้ไข
แก้ไขข้อผิดพลาดเกี่ยวกับชั้นเรียนที่ซ้ำกัน
หากคลาสปรากฏมากกว่า 1 ครั้งใน classpath รันไทม์ คุณจะได้รับข้อผิดพลาดที่คล้ายกับต่อไปนี้
Program type already present com.example.MyClass
ข้อผิดพลาดนี้มักเกิดขึ้นเนื่องจากสถานการณ์อย่างใดอย่างหนึ่งต่อไปนี้
- Dependency แบบไบนารีประกอบด้วยไลบรารีที่แอปของคุณรวมไว้ด้วยในฐานะ Dependency โดยตรง เช่น แอปของคุณประกาศว่าขึ้นต่อกันโดยตรงกับไลบรารี ก และไลบรารี ข แต่ไลบรารี ก มีไลบรารี ข รวมอยู่ในไบนารีอยู่แล้ว
- วิธีแก้ปัญหานี้คือนําไลบรารี ข. ออกในฐานะทรัพยากรที่ต้องพึ่งพาโดยตรง
- แอปของคุณมีทรัพยากร Dependency แบบไบนารีในเครื่องและแบบไบนารีระยะไกลในไลบรารีเดียวกัน
- วิธีแก้ปัญหานี้คือนําข้อกําหนดของไบนารีรายการใดรายการหนึ่งออก
แก้ไขความขัดแย้งระหว่าง classpath
เมื่อ Gradle แก้ปัญหา classpath ของคอมไพล์ ก็จะแก้ปัญหา classpath ของรันไทม์ก่อน แล้วใช้ผลลัพธ์เพื่อพิจารณาว่าควรเพิ่มการพึ่งพาเวอร์ชันใดลงใน classpath ของคอมไพล์ กล่าวคือ รันไทม์คลาสพาธจะกำหนดหมายเลขเวอร์ชันที่จำเป็นสำหรับไลบรารีที่ใช้ร่วมกันในคลาสพาธดาวน์สตรีม
คลาสพาธรันไทม์ของแอปจะกำหนดหมายเลขเวอร์ชันที่ Gradle ต้องใช้สำหรับไลบรารีที่เกี่ยวข้องซึ่งตรงกันในคลาสพาธรันไทม์สำหรับ APK การทดสอบของแอปด้วย ลำดับชั้นของ classpath มีคำอธิบายอยู่ในรูปที่ 1
ข้อขัดแย้งที่ทรัพยากร Dependency เดียวกันปรากฏใน classpath หลายรายการอาจเกิดขึ้นได้เมื่อแอปของคุณมีทรัพยากร Dependency เวอร์ชันหนึ่งที่ใช้implementation
การกำหนดค่า Dependency และโมดูลไลบรารีมีทรัพยากร Dependency เวอร์ชันอื่นที่ใช้การกำหนดค่า runtimeOnly
เมื่อแก้ไขการพึ่งพาในรันไทม์และ classpath ขณะคอมไพล์ ปลั๊กอิน Gradle ของ Android เวอร์ชัน 3.3.0 ขึ้นไปจะพยายามแก้ไขข้อขัดแย้งของเวอร์ชันดาวน์สตรีมบางรายการโดยอัตโนมัติ ตัวอย่างเช่น หาก classpath รันไทม์มีไลบรารี ก เวอร์ชัน 2.0 และ classpath การคอมไพล์มีไลบรารี ก เวอร์ชัน 1.0 ปลั๊กอินจะอัปเดตทรัพยากร Dependency ใน classpath การคอมไพล์เป็นไลบรารี ก เวอร์ชัน 2.0 โดยอัตโนมัติเพื่อหลีกเลี่ยงข้อผิดพลาด
อย่างไรก็ตาม หาก classpath รันไทม์มีไลบรารี ก เวอร์ชัน 1.0 และ classpath การคอมไพล์มีไลบรารี ก เวอร์ชัน 2.0 ปลั๊กอินจะไม่ดาวน์เกรดการพึ่งพา classpath การคอมไพล์เป็นไลบรารี ก เวอร์ชัน 1.0 และคุณยังคงได้รับข้อผิดพลาดที่คล้ายกับข้อความต่อไปนี้
Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'. Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.
หากต้องการแก้ไขปัญหานี้ ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
- ใส่ Dependency เวอร์ชันที่ต้องการเป็น
api
Dependency ลงในข้อบังคับของโมดูลไลบรารี กล่าวคือ มีเพียงโมดูลไลบรารีเท่านั้นที่ประกาศทรัพยากร Dependency แต่โมดูลแอปจะเข้าถึง API ของไลบรารีนั้นแบบทรานซิทีฟได้ด้วย - หรือจะประกาศ Dependency ในทั้ง 2 โมดูลก็ได้ แต่คุณควรตรวจสอบว่าแต่ละโมดูลใช้ Dependency เวอร์ชันเดียวกัน ลองกำหนดค่าพร็อพเพอร์ตี้ทั้งโปรเจ็กต์เพื่อให้แน่ใจว่าเวอร์ชันของ Dependency แต่ละรายการจะยังคงสอดคล้องกันตลอดทั้งโปรเจ็กต์