ניפוי באגים במקרים של שגיאות שקשורות לפתרון התלות

כשמוסיפים תלות, יכול להיות שתיתקלו בבעיות שקשורות ליחסי התלות הנדרשים לפי התלות המקורית, והתנגשויות בין גרסאות של תלות שונות. כאן מוסבר איך לנתח את תרשים התלות ולתקן בעיות נפוצות שעולות.

לקבלת הדרכה על תיקון שגיאות של יישוב מחלוקות שקשורות ל-build בהתאמה אישית לוגיקה, אסטרטגיות מותאמות אישית לרזולוציית תלות.

הצגת יחסי התלות של מודולים

יחסי תלות ישירים מסוימים עשויים להיות תלויים משל עצמם. האירועים האלה מכונים יחסי תלות עוברים. במקום לדרוש מכם להצהיר ידנית על כל אחד מהכרטיסים של תלות במעבר, Gradle אוספת אוטומטית ומוסיפה אותם בשבילכם. בפלאגין של Android ל-Gradle יש משימה שמציגה רשימה של יחסי התלות ש-Gradle פותרים במודול נתון.

עבור כל מודול, הדוח גם מקבצת את יחסי התלות על סמך הווריאנט של ה-build, קבוצת המקור שנבדקת נתיב הכיתה. הדוגמה הבאה היא דוח בזמן הריצה של מודול האפליקציה classpath של הווריאנט של גרסת ה-build של ניפוי הבאגים ולהרכיב classpath של האינסטרומנטציה שלו מקור הבדיקה שהוגדר.

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
...

כדי להפעיל את המשימה, צריך לבצע את הפעולות הבאות:

  1. בוחרים באפשרות תצוגה > Windows בכלי > Gradle (או לחיצה) Gradle בסרגל הכלים של Google.
  2. הרחבה AppName > משימות > Android וגם לוחצים לחיצה כפולה על androidDependencies. אחרי ההפעלה של Gradle המשימה, החלון Run אמור להיפתח כדי להציג את הפלט.

למידע נוסף על ניהול יחסי התלות ב-Gradle ראו העקרונות הבסיסיים של ניהול יחסי התלות במדריך למשתמש של Gradle.

החרגה של יחסי תלות טרנזיים

ככל שהיקף ההרשאות של האפליקציה גדל, היא עשויה לכלול כמה יחסי תלות, יחסי תלות ישירים ויחסי תלות טרנזיים (ספריות שה שבו ספריות מיובאות תלויות). כדי להחריג יחסי תלות טרנזיים שאתם לא צריכים יותר, אפשר להשתמש מילת מפתח אחת (exclude) כמו שמפורט בהמשך:

Kotlin

dependencies {
    implementation("some-library") {
        exclude(group = "com.example.imgtools", module = "native")
    }
}

מגניב

dependencies {
    implementation('some-library') {
        exclude group: 'com.example.imgtools', module: 'native'
    }
}

החרגה של יחסי תלות מעבריביים מהגדרות הבדיקה

אם צריך להחריג מהבדיקות יחסי תלות מסוימים טרנזקטיביים, יכול להיות שדוגמת הקוד שמוצגת למעלה לא תפעל כצפוי. הסיבה לכך היא שהבדיקה (למשל, androidTestImplementation) מרחיב את שטח המודול הגדרה של implementation. כלומר, תמיד מכיל implementation של יחסי התלות כש-Gradle פותר את הגדרת התצורה.

לכן, כדי להחריג מהבדיקות יחסי תלות טרנזיים, צריך לעשות זאת זמן הביצוע כפי שמוצג בהמשך:

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 בבלוק של יחסי התלות, כפי שמוצג בדוגמת הקוד המקורית החרגה של יחסי תלות טרנזיים להשמיט יחסי תלות טרנזיים שהם ספציפיים לניסוי ולא נכללים בהגדרות אחרות.

תיקון שגיאות בפתרון של התלות

כשמוסיפים יחסי תלות מרובים לפרויקט האפליקציה, הקישורים הישירים האלה יחסי תלות מעבריביים עלולים להתנגש זה עם זה. Android Gradle מנסה לפתור את ההתנגשויות האלה באלגנטיות, אך התנגשויות מסוימות עלולות להוביל כדי להדר שגיאות זמן או שגיאות זמן ריצה.

כדי לעזור לכם לבדוק אילו יחסי תלות גורמים לשגיאות, לבדוק את עץ התלות של האפליקציה ולחפש של יחסי התלות שמופיעים יותר מפעם אחת או עם גרסאות מתנגשות.

אם לא ניתן לזהות בקלות את התלות הכפולה, כדאי לנסות להשתמש ב-Android ממשק המשתמש של Studio לחיפוש יחסי תלות שכוללים את המחלקה הכפולה ככה:

  1. בוחרים באפשרות ניווט > שיעור בסרגל התפריטים.
  2. בתיבת הדו-שיח של החיפוש הקופצת, מוודאים שהתיבה שלצד התיבה הכללת פריטים שאינם בפרויקט מסומנת.
  3. מקלידים את שם המחלקה שמופיעה בשגיאת ה-build.
  4. בודקים את התוצאות של יחסי התלות שכוללים את המחלקה.

בקטעים הבאים מתוארים הסוגים השונים של יישוב יחסי תלות ייתכן שתיתקלו בשגיאות האלו והדרכים לתקן אותן.

תיקון שגיאות כפולות בכיתה

אם כיתה תופיע יותר מפעם אחת בנתיב הכיתה בסביבת זמן הריצה, תקבלו שדומה לשגיאה הבאה:

Program type already present com.example.MyClass

בדרך כלל שגיאה זו מתרחשת בשל אחת מהנסיבות הבאות:

  • תלות בינארית כוללת ספרייה שהאפליקציה שלך כוללת גם תלות ישירה. לדוגמה, האפליקציה שלך מצהירה על תלות ישירה ספרייה א' וספרייה ב', אבל ספרייה א' כבר כוללת את ספרייה ב' בינארית.
    • כדי לפתור את הבעיה, צריך להסיר את 'ספרייה ב' כתלות ישירה.
  • לאפליקציה שלך יש תלות בינארית מקומית ותלות בינארית מרחוק בקובץ מאותה ספרייה.
    • כדי לפתור את הבעיה הזו, מסירים את אחד יחסי התלות הבינאריים.

תיקון התנגשויות בין נתיבי כיתה

כש-Gradle מזהה ב-Gradle את נתיב ה-classpath, הוא פותר את זמן הריצה. classpath ומשתמשת בתוצאה כדי לקבוע אילו גרסאות של יחסי תלות לנתיב הכיתה של הידור. במילים אחרות, סביבת זמן הריצה classpath קובע את מספרי הגרסאות הנדרשים ליחסי תלות זהים במסלולי הכיתה במורד הזרם.

גם מספרי הגרסאות ש-Gradle מציין נדרש להתאמה של יחסי תלות בנתיב classpath של זמן הריצה לבדיקה של האפליקציה APK ההיררכיה של נתיבי הכיתה מתוארת באיור 1.

איור 1. מספרי גרסאות של יחסי תלות שמופיעות במספר נתיבי כיתה, חייבים להיות תואמים ההיררכיה.

התנגשות שבה מופיעות גרסאות שונות של אותה תלות נתיבי כיתות מרובים עשויים להתרחש כאשר, לדוגמה, האפליקציה כוללת גרסה של תלות באמצעות הפונקציה implementation הגדרת יחסי תלות ומודול ספרייה כולל גרסה אחרת של התלות באמצעות ההגדרה האישית runtimeOnly.

בפתרון יחסי התלות בזמן הריצה ולהקליד נתיבי כיתת זמן, Android פלאגין של Gradle בגרסה 3.3.0 ומעלה, בניסיון לתקן באופן אוטומטי חלק מה-downstream גרסאות מתנגשות. לדוגמה, אם ה-classpath של סביבת זמן הריצה כולל את 'ספרייה א' גרסה 2.0 וה-Classpath להדר כולל את 'ספרייה א' גרסה 1.0, הפלאגין מעדכנת באופן אוטומטי את התלות בנתיב הכיתה להדר אל 'ספרייה א' גרסה 2.0 כדי למנוע שגיאות.

עם זאת, אם נתיב הכיתה בסביבת זמן הריצה כולל את ספריית א' גרסה 1.0 ואת מערכת הידור (compile), classpath כולל את גרסה 2.0 של 'ספרייה א', הפלאגין לא משדרג לאחור את שתלויה ב-העברת כיתה ל'ספרייה א' בגרסה 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.

כדי לפתור את הבעיה, אפשר לבצע אחת מהפעולות הבאות:

  • לכלול את הגרסה הרצויה של התלות כתלות ב-api של מודול הספרייה. כלומר, רק מודול הספרייה מצהיר על התלות, אבל למודול האפליקציה תהיה גם גישה ל-API שלו באופן זמני.
  • לחלופין, אתם יכולים להצהיר על התלות בשני המודולים, אבל לוודא שכל מודול משתמש באותה גרסה של התלות. נקודות שכדאי להעלות הגדרה של נכסים ברמת הפרויקט כדי להבטיח שגרסאות של כל תלות יישארו עקביות לאורך הפרויקט.