
عندما لا يكون المطور حريصًا بما فيه الكفاية ، يمكن أن تسير الأمور بشكل سيء للغاية. على سبيل المثال ، تعتبر عمليات حذف المطورين الكلاسيكية هي استخدام إصدار جديد من واجهة برمجة التطبيقات غير متوافق مع الشفرة القديمة ، وتنفيذ الإجراءات التي تتطلب أذونات المستخدم الخاصة ، والثغرات الموجودة في تعريب التطبيق. وهذه ليست سوى بعض منهم.
بالإضافة إلى ذلك ، تتمتع Java و Kotlin ، مثل أي لغة برمجة أخرى ، ببنيات خاصة بها يمكن أن تؤدي إلى أداء رديء.
مرحبا ينت
نستخدم أداة تسمى Lint (أو Linter) لتجنب مثل هذه المشاكل. Lint عبارة عن أداة لتحليل الأكواد الثابتة تساعد المطورين على اكتشاف المشكلات المحتملة قبل تجميع التعليمات البرمجية. تقوم Lint بإجراء فحوصات متعددة للشفرة المصدر ، والتي يمكن أن تكشف عن مشاكل مثل المتغيرات غير المستخدمة أو وسيطات الوظائف ، وتبسيط الشروط ، والنطاق غير الصحيح ، والمتغيرات أو الوظائف غير المحددة ، والكود السيئ المحسن ، إلخ. عندما نتحدث عن تطوير نظام أندرويد ، فهناك مئات من اختبارات Lint خارج الصندوق.
لكن في بعض الأحيان نحتاج إلى العثور على مشاكل محددة في التعليمات البرمجية الخاصة بنا والتي لا تغطيها عمليات التحقق الحالية.
مرحبا الشيكات مخصص لينت
قبل أن نبدأ الترميز ، دعونا نحدد هدفنا ونرى كيفية تنفيذه خطوة بخطوة باستخدام Lint API. الهدف هو إنشاء فحص للكشف عن استدعاء أسلوب غير صحيح لكائن. تتمثل فكرة هذا الاختبار في تحديد ما إذا كانت طريقة تثبيت المستمع على مكون العرض هي الطريقة التي ستقاطع عدة نقرات متتالية على المكون حتى يمكننا تجنب فتح نفس النشاط أو الوصول إلى الشبكة عدة مرات.
تتم كتابة اختبارات مستخدم Lint كجزء من وحدة Java القياسية (أو Kotlin). أسهل طريقة للبدء هي إنشاء مشروع بسيط قائم على Gradle (لا يجب أن يكون مشروع Android).
ثم أضف تبعيات لينت. في ملف build.gradle
من الوحدة النمطية الخاصة بك ، أضف:
compileOnly "com.android.tools.lint:lint-api:$lintVersion" compileOnly "com.android.tools.lint:lint-checks:$lintVersion"
الآن هناك خدعة تعلمت عنها عند البحث في هذا الموضوع. يجب أن يكون gradlePluginVersion + 23.0.0
. gradlePluginVersion
هو متغير معرف في ملف build.gradle
على مستوى المشروع. وفي الوقت الحالي ، أحدث إصدار مستقر هو 3.3.0. هذا يعني أن lintVersion
يجب أن يكون 26.3.0.
يتكون كل فحص ينت من 4 أجزاء:
- المشكلة هي المشكلة في التعليمات البرمجية التي نحاول منعها. عندما يفشل فحص Lint ، يتم إبلاغ هذا للمطور.
- Detector عبارة عن أداة لإيجاد المشكلات توفر Lint API.
- التنفيذ هو منطقة قد تنشأ فيها مشكلة (الملف المصدر ، ملف XML ، التعليمات البرمجية المترجمة ، إلخ).
- السجل هو سجل فحص Lint مخصص سيتم استخدامه مع سجل موجود يحتوي على اختبارات محددة مسبقًا.
تطبيق
لنبدأ بإنشاء تطبيق للتحقق من صحة مخصص لدينا. يتكون كل تطبيق من فئة تقوم بتنفيذ كاشف ونطاق.
val correctClickListenerImplementation = Implementation(CorrectClickListenerDetector::class.java, Scope.JAVA_FILE_SCOPE)
تذكر أن Scope.JAVA_FILE_SCOPE
سيعمل أيضًا مع فصول Kotlin.
المشكلة
الخطوة التالية هي استخدام هذا التطبيق لتحديد المشكلة. تتكون كل مشكلة من عدة أجزاء:
- المعرف هو معرف فريد.
- الوصف - بيان قصير (5-6 كلمات) للمشكلة.
- الشرح شرح كامل للمشكلة مع اقتراح حول كيفية إصلاح هذا.
- الفئة - فئة المشكلة (الأداء ، الترجمة ، الأمان ، إلخ).
- الأولوية - أهمية المشكلة ، في حدود 1 إلى 10 ، حيث 10 هي الأعلى. سيتم استخدام هذا لفرز المشكلات في التقرير الذي تم إنشاؤه عند إطلاق Lint.
- درجة الخطورة - خطورة المشكلة (قاتلة أو خطأ أو تحذير أو معلومات أو تجاهل).
- التنفيذ هو تطبيق سيتم استخدامه للكشف عن هذه المشكلة.
val ISSUE_CLICK_LISTENER = Issue.create( id = "UnsafeClickListener", briefDescription = "Unsafe click listener", explanation = """" This check ensures you call click listener that is throttled instead of a normal one which does not prevent double clicks. """.trimIndent(), category = Category.CORRECTNESS, priority = 6, severity = Severity.WARNING, implementation = correctClickListenerImplementation )
كاشف
يوفر Lint API واجهات لكل منطقة يمكنك تحديدها في التنفيذ. توفر كل من هذه الواجهات طرقًا يمكنك تجاوزها والوصول إلى أجزاء من التعليمات البرمجية التي تهمك.
- UastScanner - ملفات Java أو Kotlin (UAST - شجرة بناء الجملة الموحدة ( شجرة بناء الجملة الروسية الموحدة )).
- ClassScanner - الملفات المترجمة (bytecode).
- BinaryResourceScanner - موارد ثنائية مثل الصور النقطية أو ملفات
res/raw
. - ResourceFolderScanner - مجلدات الموارد (ليست ملفات محددة فيها).
- XmlScanner - ملفات XML.
- GradleScanner - ملفات Gradle.
- OtherFileScanner - كل شيء آخر.
بالإضافة إلى ذلك ، تعد فئة Detector
فئة أساسية تحتوي على تطبيقات فارغة لجميع الطرق التي توفرها كل من الواجهات المذكورة أعلاه ، لذلك لا تحتاج إلى تنفيذ الواجهة الكاملة في حالة احتياجك إلى طريقة واحدة فقط.
نحن الآن على استعداد لتنفيذ كاشف يقوم بفحص استدعاء الأسلوب الصحيح للكائن.
private const val REPORT_MESSAGE = "Use setThrottlingClickListener" class CorrectClickListenerDetector : Detector(), Detector.UastScanner { override fun getApplicableUastTypes(): List<Class<out UElement>>? { return listOf<Class<out UElement>>(UCallExpression::class.java) } /** * UAST, , * UAST . UElementHandler, * , , * , , , , .. * , * . — , * , , . */ override fun createUastHandler(context: JavaContext): UElementHandler? { return object: UElementHandler() { override fun visitCallExpression(node: UCallExpression) { if (node.methodName != null && node.methodName?.equals("setOnClickListener", ignoreCase = true) == true) { context.report(ISSUE_CLICK_LISTENER, node, context.getLocation(node), REPORT_MESSAGE, createFix()) } } } } private fun createFix(): LintFix { return fix().replace().text("setOnClickListener").with("setThrottlingClickListener").build() } }
السجل
آخر شيء نحتاج إلى القيام به هو إضافة مشاكل إلى السجل الخاص بنا وإخبار Lint بوجود سجل خاص للمشاكل يجب استخدامه مع السجل القياسي.
class MyIssueRegistry : IssueRegistry() { override val issues: List<Issue> = listOf(ISSUE_CLICK_LISTENER) }
في build.gradle
مستوى الوحدة:
jar { manifest { attributes("Lint-Registry-v2": "co.infinum.lint.MyIssueRegistry") } }
حيث co.infinum.lint
عبارة عن حزمة من فئة MyIssueRegistry
. يمكنك الآن تشغيل مهمة jar
باستخدام البرنامج النصي gradlew
، ويجب أن تظهر المكتبة في دليل build/libs
.
إليك مثال آخر على فحص مستخدم Lint ، حيث يمكنك معرفة كيفية معالجة ملفات XML.
استخدام
فحص Lint الجديد الخاص بك جاهز للاستخدام في المشروع. إذا كان يمكن تطبيق هذا التحقق على جميع المشاريع ، يمكنك وضعه في مجلد ~/.android/lint
(يمكنك إنشائه إذا لم يكن موجودًا بالفعل).
بالإضافة إلى ذلك ، يمكنك وضع الفحص في وحدة منفصلة في مشروعك وتمكين هذه الوحدة مثل أي تبعية أخرى باستخدام طريقة lintChecks
.
هل يستحق كل هذا العناء؟
Lint أداة جيدة حقًا يجب على كل مطور استخدامها. تعد القدرة على اكتشاف المشكلات المحتملة في الكود مبكرًا مفيدة للغاية. على الرغم من أن الشيكات المخصصة ليست سهلة في الكتابة ، ويرجع ذلك أساسًا إلى تعقيد واجهة برمجة التطبيقات ، إلا أنها تستحق ذلك بالتأكيد ويمكن أن توفر لك الكثير من الوقت والجهد في المستقبل.