تصحيح أخطاء حل التبعية

عند إضافة تبعية، قد تواجه مشكلات مع التبعيات المطلوبة من خلال التبعية الأصلية، وتعارضات بين إصدارات التبعية المختلفة. إليك كيفية تحليل الرسم البياني للتبعية وإصلاح المشاكل الشائعة التي تنشأ.

للحصول على إرشادات حول إصلاح أخطاء حل التبعية التي تتضمّن منطق إصدار مخصَّص، يُرجى الاطّلاع على استراتيجيات حلّ التبعية المخصَّصة.

عرض تبعيات الوحدات

قد يكون لبعض التبعيات المباشرة تبعيات خاصة بها. وتسمى هذه التبعيات الانتقالية. بدلاً من أن تطلب منك الإفصاح يدويًا عن كل تبعية عابرة، تجمع 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
...

لتشغيل المهمة، اتّبِع الخطوات التالية:

  1. اختَر عرض > أداة Windows > Gradle (أو انقر على أداة Gradle في شريط نوافذ الأدوات).
  2. وسِّع AppName > "مهام Google" > android وانقر مرّتين على androidExpirationiness. بعد تنفيذ 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. اكتب اسم الفئة الذي يظهر في خطأ الإصدار.
  4. افحص نتائج التبعيات التي تتضمن الفئة.

تصف الأقسام التالية الأنواع المختلفة من أخطاء حل التبعية التي قد تواجهها وكيفية إصلاحها.

إصلاح أخطاء الصف المكرّرة

فإذا ظهرت فئة أكثر من مرة على مسار الفئة في وقت التشغيل، فستحصل على خطأ مشابه لما يلي:

Program type already present com.example.MyClass

يحدث هذا الخطأ عادةً بسبب أحد الحالات التالية:

  • تتضمن التبعية الثنائية مكتبة يتضمنها تطبيقك أيضًا كتبعية مباشرة. على سبيل المثال، يشير تطبيقك إلى اعتماد مباشر على المكتبة "أ" والمكتبة "ب"، إلا أنّ المكتبة "أ" تتضمّن المكتبة "ب" في ملفها الثنائي.
    • لحلّ هذه المشكلة، عليك إزالة المكتبة "ب" كتبعية مباشرة.
  • يحتوي تطبيقك على تبعية ثنائية محلية وتبعية ثنائية عن بُعد على المكتبة نفسها.
    • لحلّ هذه المشكلة، عليك إزالة إحدى التبعيات الثنائية.

إصلاح التعارضات بين مسارات الصفوف

عندما يحل Gradle مسار فئة التجميع، فإنه يحل أولاً مسار الفئة وقت التشغيل ويستخدم النتيجة لتحديد إصدارات التبعيات التي ينبغي إضافتها إلى مسار فئة التجميع. بمعنى آخر، يحدد مسار فئة وقت التشغيل أرقام الإصدار المطلوبة للتبعيات المتطابقة على مسارات الفئات النهائية.

يحدد مسار فئة وقت تشغيل تطبيقك أيضًا أرقام الإصدار التي يتطلبها تطبيق Gradle لمطابقة التبعيات في مسار فئة وقت التشغيل لملف APK الاختباري للتطبيق. يتم وصف التسلسل الهرمي لمسارات الفئات في الشكل 1.

الشكل 1. يجب أن تتطابق أرقام إصدارات التبعيات التي تظهر على مسارات فئات متعددة وفقًا لهذا التسلسل الهرمي.

التعارض الذي قد تظهر فيه إصدارات مختلفة من التبعية نفسها على مستوى مسارات فئات متعددة عندما يتضمّن تطبيقك مثلاً إصدارًا من التبعية باستخدام implementation إعداد التبعية وتتضمّن وحدة المكتبة إصدارًا مختلفًا من التبعية باستخدام إعدادات runtimeOnly.

عند حل مشكلة الاعتماديات على وقت التشغيل وتجميع مسارات فئات الوقت، يحاول المكوّن الإضافي Android Gradle 3.3.0 والإصدارات الأحدث إصلاح بعض التعارضات في إصدارات المراحل اللاحقة تلقائيًا. على سبيل المثال، إذا كان مسار الفئة وقت التشغيل يتضمن الإصدار 2.0 من المكتبة أ بينما كان مسار فئة التجميع يتضمن الإصدار 1.0 من المكتبة أ، سيحدّث المكوّن الإضافي تلقائيًا التبعية على مسار فئة التجميع إلى الإصدار 2.0 من المكتبة A لتجنُّب حدوث أخطاء.

ومع ذلك، إذا كان مسار فئة وقت التشغيل يتضمن الإصدار 1.0 من المكتبة أ أمّا مسار فئة التجميع يتضمن الإصدار 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 إلى وحدة مكتبتك. وهذا يعني أن وحدة المكتبة فقط هي التي تعلن عن التبعية، ولكن سيكون بإمكان وحدة التطبيق أيضًا الوصول إلى واجهة برمجة التطبيقات الخاصة بها، بشكل تبادلي.
  • بدلاً من ذلك، يمكنك تعريف التبعية في كلتا الوحدتين، ولكن يجب عليك التأكد من أن كل وحدة تستخدم نفس إصدار التبعية. ضع في اعتبارك تهيئة الخصائص على مستوى المشروع لضمان بقاء إصدارات كل تبعية متسقة طوال مشروعك.