เมื่อเพิ่มทรัพยากร Dependency แล้ว คุณอาจพบปัญหาเกี่ยวกับทรัพยากร Dependency ที่จำเป็น ตามทรัพยากร Dependency เดิม และความขัดแย้งระหว่างทรัพยากร Dependency ในเวอร์ชันต่างๆ ต่อไปนี้คือวิธีวิเคราะห์กราฟทรัพยากร Dependency และแก้ไขปัญหาทั่วไปที่เกิดขึ้น
สำหรับคำแนะนำเกี่ยวกับการแก้ไขข้อผิดพลาดด้านการแก้ไขทรัพยากร Dependency ที่เกี่ยวข้องกับบิลด์ที่กำหนดเอง ตรรกะ, ดู กลยุทธ์การแก้ปัญหาทรัพยากร Dependency ที่กำหนดเอง
ดูการอ้างอิงโมดูล
ทรัพยากร Dependency โดยตรงบางรายการอาจมีทรัพยากร Dependency ของตนเอง ทั้งหมดนี้เรียกว่า ทรัพยากร Dependency แบบสโลแกน แทนที่จะกำหนดให้คุณประกาศแต่ละรายการเอง ทรัพยากร Dependency แบบทรานซิทีฟ Gradle จะรวบรวมและเพิ่ม ให้กับคุณโดยอัตโนมัติ ปลั๊กอิน Android สำหรับ Gradle จะมีงานที่แสดงรายการ ทรัพยากร Dependency ที่ Gradle จะแก้ไขสำหรับโมดูลที่กำหนด
สำหรับแต่ละโมดูล รายงาน จัดกลุ่มทรัพยากร Dependency ตามตัวแปรของบิลด์ ชุดแหล่งที่มาของการทดสอบ และ คลาสพาธ ต่อไปนี้คือรายงานตัวอย่างสำหรับรันไทม์ของโมดูลแอป คลาสพาธของตัวแปรบิลด์การแก้ไขข้อบกพร่องและคอมไพล์คลาสพาธของเวอร์ชันที่มีการวัด ชุดแหล่งที่มาทดสอบ
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 > งาน > android และ ดับเบิลคลิก androidDependencies หลังจาก Gradle ดำเนินการ งานนั้น หน้าต่าง Run ควรเปิดขึ้นเพื่อแสดงเอาต์พุต
ดูข้อมูลเพิ่มเติมเกี่ยวกับการจัดการทรัพยากร Dependency ใน Gradle ได้ที่ ข้อมูลเบื้องต้นเกี่ยวกับการจัดการการขึ้นต่อกัน ในคู่มือผู้ใช้ Gradle
ไม่รวมการอ้างอิงแบบสับเปลี่ยน
เมื่อแอปเติบโตขึ้น แอปอาจมีทรัพยากร Dependency ต่างๆ มากมาย เช่น
ทรัพยากร Dependency โดยตรงและการอ้างอิงแบบทรานซิทีฟ (ไลบรารีที่แอปของคุณ
ไลบรารีที่นำเข้าจะขึ้นอยู่กับ)
หากต้องการยกเว้นทรัพยากร Dependency แบบทรานซิทีฟที่ไม่ต้องการแล้ว คุณสามารถใช้เมธอด
exclude
คีย์เวิร์ดตามที่ระบุไว้ด้านล่าง
Kotlin
dependencies { implementation("some-library") { exclude(group = "com.example.imgtools", module = "native") } }
ดึงดูด
dependencies { implementation('some-library') { exclude group: 'com.example.imgtools', module: 'native' } }
ไม่รวมทรัพยากร Dependency แบบทรานซิทีฟจากการกำหนดค่าการทดสอบ
หากคุณต้องการยกเว้นทรัพยากร Dependency แบบทรานซิทีฟบางรายการจากการทดสอบ
ตัวอย่างโค้ดที่แสดงด้านบนอาจไม่ทำงานตามที่คาดไว้ นั่นเป็นเพราะการทดสอบ
การกำหนดค่า (เช่น androidTestImplementation
) ขยายโมดูล
การกำหนดค่า implementation
กล่าวคือ จะมี implementation
เสมอ
ทรัพยากร Dependency เมื่อ Gradle แก้ไขการกำหนดค่า
ดังนั้น หากต้องการยกเว้นทรัพยากร Dependency แบบทรานซิทีฟจากการทดสอบของคุณ คุณต้องทำที่ เวลาดำเนินการดังที่แสดงด้านล่าง
Kotlin
android.testVariants.all { compileConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp") runtimeConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp") }
ดึงดูด
android.testVariants.all { variant -> variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp' variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp' }
หมายเหตุ: คุณยังคงใช้คีย์เวิร์ด exclude
ได้อยู่
ในบล็อกทรัพยากร Dependency ดังที่แสดงในตัวอย่างโค้ดต้นฉบับจาก
ไม่รวมทรัพยากร Dependency แบบทรานซิทีฟ
เพื่อละเว้นทรัพยากร Dependency แบบทรานซิทีฟที่เฉพาะเจาะจงกับการทดสอบ
และไม่รวมอยู่ในการกำหนดค่าอื่นๆ
แก้ไขข้อผิดพลาดเกี่ยวกับการแปลงทรัพยากร Dependency
เมื่อคุณเพิ่มทรัพยากร Dependency หลายรายการลงในโปรเจ็กต์แอป ทรัพยากรโดยตรงและ ทรัพยากร Dependency แบบสับเปลี่ยนอาจขัดแย้งกัน Android Gradle ปลั๊กอินจะพยายามแก้ไขความขัดแย้งเหล่านี้อย่างสวยงาม แต่ข้อขัดแย้งบางอย่างก็อาจทำให้เกิด เพื่อรวบรวมข้อผิดพลาดเกี่ยวกับเวลาหรือรันไทม์
เพื่อช่วยคุณตรวจสอบว่าทรัพยากร Dependency ใดที่ทำให้เกิดข้อผิดพลาด ตรวจสอบแผนผังทรัพยากร Dependency ของแอปและมองหา ทรัพยากร Dependency ที่ปรากฏมากกว่า 1 ครั้งหรือปรากฏขึ้นพร้อมกับเวอร์ชันที่ขัดแย้งกัน
หากคุณระบุทรัพยากร Dependency ที่ซ้ำกันได้ยาก ให้ลองใช้ Android UI ของ Studio สำหรับค้นหาทรัพยากร Dependency ที่มีคลาสที่ซ้ำกัน ดังนี้
- เลือก นำทาง > ชั้นเรียนจากแถบเมนู
- ในกล่องโต้ตอบการค้นหาแบบป๊อปอัป ให้ตรวจสอบว่าช่องทำเครื่องหมายข้าง มีการเลือกรวมรายการที่ไม่ใช่โปรเจ็กต์ไว้
- พิมพ์ชื่อชั้นเรียนที่ปรากฏในข้อผิดพลาดของบิลด์
- ตรวจสอบผลลัพธ์ของทรัพยากร Dependency ที่มีคลาส
ส่วนต่อไปนี้จะอธิบายความละเอียดของทรัพยากร Dependency ประเภทต่างๆ ที่คุณอาจพบและวิธีแก้ไข
แก้ไขข้อผิดพลาดของชั้นเรียนที่ซ้ำกัน
หากคลาสปรากฏใน classpath แบบรันไทม์มากกว่า 1 ครั้ง คุณจะได้รับ ที่คล้ายกับข้อความต่อไปนี้
Program type already present com.example.MyClass
ข้อผิดพลาดนี้มักเกิดจากสาเหตุใดกรณีหนึ่งต่อไปนี้
- ทรัพยากร Dependency แบบไบนารีมีไลบรารีที่แอปของคุณรวมไว้ด้วยเป็น
การขึ้นต่อกันโดยตรง ตัวอย่างเช่น แอปของคุณประกาศว่าการขึ้นต่อกันโดยตรงใน
ไลบรารี ก และไลบรารี ข แต่ไลบรารี ก รวมไลบรารี ข ไว้ใน
2.
- หากต้องการแก้ไขปัญหานี้ ให้นำไลบรารี B ที่เป็นทรัพยากร Dependency โดยตรงออก
- แอปของคุณมีทรัพยากร Dependency แบบไบนารีในเครื่องและการอ้างอิงแบบไบนารีระยะไกล
ไลบรารีเดียวกัน
- หากต้องการแก้ไขปัญหานี้ ให้นำทรัพยากร Dependency แบบไบนารีออก 1 รายการ
แก้ไขความขัดแย้งระหว่างเส้นทางคลาส
เมื่อ Gradle แก้ไขคลาสพาธของคอมไพล์ ให้แก้รันไทม์ก่อน คลาสพาธและใช้ผลลัพธ์เพื่อกำหนดเวอร์ชันของทรัพยากร Dependency ที่ควร ลงในคอมไพล์คลาสพาธ กล่าวคือ รันไทม์ classpath จะกำหนดหมายเลขเวอร์ชันที่จำเป็นสำหรับทรัพยากร Dependency ที่เหมือนกันใน ชั้นเรียนที่ปลายสตรีม
คลาสพาธรันไทม์ของแอปจะกำหนดหมายเลขเวอร์ชันที่ Gradle ต้องใช้สำหรับทรัพยากร Dependency ที่ตรงกันในคลาสพาธรันไทม์สำหรับการทดสอบของแอป APK ลำดับชั้นของคลาสพาธอธิบายไว้ในรูปที่ 1
ข้อขัดแย้งที่ทรัพยากร Dependency เดียวกันเวอร์ชันต่างๆ ปรากฏขึ้น
คลาสพาธหลายรายการอาจเกิดขึ้นเมื่อแอปมีเวอร์ชันของ
ทรัพยากร Dependency โดยใช้ implementation
การกำหนดค่าการขึ้นต่อกัน
และโมดูลไลบรารีจะมี Dependency เวอร์ชันต่างๆ โดยใช้
การกำหนดค่า runtimeOnly
เมื่อแก้ไขทรัพยากร Dependency ของรันไทม์และคอมไพล์เส้นทางคลาสเวลา, Android ปลั๊กอิน Gradle 3.3.0 ขึ้นไปจะพยายามแก้ไขดาวน์สตรีมบางรายการโดยอัตโนมัติ ความขัดแย้งของเวอร์ชัน ตัวอย่างเช่น หากคลาสพาธรันไทม์มีไลบรารี A เวอร์ชัน 2.0 และ compile classpath ประกอบด้วยไลบรารี A เวอร์ชัน 1.0 และปลั๊กอิน อัปเดต Dependency ของคลาสพาธคอมไพล์ไปยังไลบรารี A โดยอัตโนมัติ เวอร์ชัน 2.0 เพื่อหลีกเลี่ยงข้อผิดพลาด
แต่หากคลาสพาธรันไทม์มีไลบรารี A เวอร์ชัน 1.0 และคอมไพล์ classpath มีไลบรารี A เวอร์ชัน 2.0 แต่ปลั๊กอินจะไม่ปรับลดรุ่น ขึ้นอยู่กับคลาสพาธการคอมไพล์ไปยังไลบรารี A เวอร์ชัน 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 เวอร์ชันที่ต้องการเป็นทรัพยากร Dependency
api
ของคุณ โมดูลไลบรารี กล่าวคือ มีเพียงโมดูลไลบรารีของคุณเท่านั้นที่จะประกาศทรัพยากร Dependency โมดูลแอปจะมีสิทธิ์เข้าถึง API แบบทางอ้อมด้วย - อีกทางเลือกหนึ่งคือคุณสามารถประกาศ Dependency ในทั้ง 2 โมดูลได้ แต่คุณควร ตรวจสอบว่าแต่ละโมดูลใช้ทรัพยากร Dependency เวอร์ชันเดียวกัน พิจารณา การกำหนดค่าพร็อพเพอร์ตี้ของทั้งโปรเจ็กต์ เพื่อให้มั่นใจว่าทรัพยากร Dependency แต่ละเวอร์ชันจะสอดคล้องกันตลอดทั้งโปรเจ็กต์