Was ist Android Lint und wie können Sie unterstützten Code schreiben?

Was ist Android Lint und wie können Sie unterstützten Code schreiben?


Wenn der Entwickler nicht vorsichtig genug ist, kann es sehr schlecht laufen. Die klassischen Entwicklerauslassungen sind beispielsweise die Verwendung einer neuen Version der API, die nicht mit dem alten Code kompatibel ist, die Ausführung von Aktionen, für die spezielle Benutzerberechtigungen erforderlich sind, und Lücken in der Lokalisierung der Anwendung. Und das sind nur einige davon.


Darüber hinaus verfügen Java und Kotlin wie jede andere Programmiersprache über eigene Konstrukte, die zu einer schlechten Leistung führen können.


Hallo Fussel


Wir verwenden ein Tool namens Lint (oder Linter), um solche Probleme zu vermeiden. Lint ist ein statisches Code-Analyse-Tool, mit dem Entwickler potenzielle Probleme erkennen können, bevor der Code kompiliert wird. Lint führt mehrere Überprüfungen des Quellcodes durch, wodurch Probleme wie nicht verwendete Variablen oder Funktionsargumente, Vereinfachung von Bedingungen, falscher Umfang, undefinierte Variablen oder Funktionen, schlecht optimierter Code usw. erkannt werden können. Wenn wir über die Android-Entwicklung sprechen, sind Hunderte von Lint-Checks sofort einsatzbereit .


Manchmal müssen wir jedoch bestimmte Probleme in unserem Code finden, die von diesen vorhandenen Prüfungen nicht abgedeckt werden.


Hallo Custom Checks Lint


Bevor wir mit dem Codieren beginnen, definieren wir unser Ziel und sehen, wie es mithilfe der Lint-API Schritt für Schritt implementiert wird. Ziel ist es, eine Prüfung zu erstellen, um einen falschen Methodenaufruf für ein Objekt zu erkennen. Mit diesem Test soll ermittelt werden, ob die Methode zum Installieren des Listeners auf der View-Komponente so ist, dass mehrere aufeinanderfolgende Klicks auf die Komponente unterbrochen werden, sodass nicht dieselbe Aktivität geöffnet oder mehrmals auf das Netzwerk zugegriffen werden kann.


Flusenbenutzerprüfungen werden als Teil des Standardmoduls Java (oder Kotlin) geschrieben. Der einfachste Weg, um loszulegen, besteht darin, ein einfaches Gradle-basiertes Projekt zu erstellen (es muss kein Android-Projekt sein).


Fügen Sie dann die Lint-Abhängigkeiten hinzu. build.gradle Datei build.gradle Ihres Moduls build.gradle hinzu:


 compileOnly "com.android.tools.lint:lint-api:$lintVersion" compileOnly "com.android.tools.lint:lint-checks:$lintVersion" 

Jetzt gibt es einen Trick, den ich bei der Erforschung dieses Themas gelernt habe. lintVersion sollte gradlePluginVersion + 23.0.0 . gradlePluginVersion ist eine Variable, die auf Projektebene in der Datei build.gradle definiert ist. Und im Moment ist die neueste stabile Version 3.3.0. Dies bedeutet, dass lintVersion sein sollte.


Jeder Lint Check besteht aus 4 Teilen:


  • Das Problem ist das Problem in unserem Code, das wir verhindern wollen. Wenn die Flusenprüfung fehlschlägt, wird dies dem Entwickler gemeldet.
  • Detector ist ein Tool zur Fehlersuche, das die Lint-API bereitstellt.
  • Eine Implementierung ist ein Bereich, in dem ein Problem auftreten kann (Quelldatei, XML-Datei, kompilierter Code usw.).
  • Eine Registrierung ist eine benutzerdefinierte Lint-Prüfregistrierung, die mit einer vorhandenen Registrierung verwendet wird, die vordefinierte Prüfungen enthält.

Implementierung


Beginnen wir mit der Erstellung einer Implementierung für unsere benutzerdefinierte Validierung. Jede Implementierung besteht aus einer Klasse, die einen Detektor und einen Bereich implementiert.


 val correctClickListenerImplementation = Implementation(CorrectClickListenerDetector::class.java, Scope.JAVA_FILE_SCOPE) 

Denken Scope.JAVA_FILE_SCOPE daran, dass Scope.JAVA_FILE_SCOPE auch für Kotlin-Klassen funktioniert.


Das Problem


Der nächste Schritt besteht darin, diese Implementierung zu verwenden, um das Problem zu bestimmen. Jedes Problem besteht aus mehreren Teilen:


  • ID ist eine eindeutige Kennung.
  • Beschreibung - eine kurze (5-6 Wörter) Erklärung des Problems.
  • Erläuterung Eine vollständige Erläuterung eines Problems mit einem Vorschlag zur Behebung dieses Problems.
  • Kategorie - Die Kategorie des Problems (Leistung, Übersetzung, Sicherheit usw.).
  • Priorität - Die Bedeutung des Problems im Bereich von 1 bis 10, wobei 10 am höchsten ist. Dies wird verwendet, um Probleme in dem Bericht zu sortieren, der beim Start von Lint erstellt wurde.
  • Schweregrad - Der Schweregrad des Problems (schwerwiegend, Fehler, Warnung, Information oder Ignorieren).
  • Eine Implementierung ist eine Implementierung, mit der dieses Problem erkannt wird.

 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 ) 

Detektor


Die Lint-API bietet Schnittstellen für jeden Bereich, den Sie in einer Implementierung definieren können. Jede dieser Schnittstellen bietet Methoden, mit denen Sie Teile des Codes überschreiben und darauf zugreifen können, die Sie interessieren.


  • UastScanner - Java- oder Kotlin-Dateien (UAST - Unified Abstract Syntax Tree (russischer einheitlicher abstrakter Syntaxbaum )).
  • ClassScanner - kompilierte Dateien (Bytecode).
  • BinaryResourceScanner - Binärressourcen wie Bitmaps oder res/raw Dateien.
  • ResourceFolderScanner - Ressourcenordner (keine bestimmten Dateien darin).
  • XmlScanner - XML-Dateien.
  • GradleScanner - Gradle-Dateien.
  • OtherFileScanner - alles andere.

Darüber hinaus ist die Detector Klasse eine Basisklasse, die leere Implementierungen aller von jeder der oben genannten Schnittstellen bereitgestellten Methoden enthält, sodass Sie nicht die vollständige Schnittstelle implementieren müssen, wenn Sie nur eine Methode benötigen.


Jetzt können wir einen Detektor implementieren, der den korrekten Methodenaufruf für das Objekt überprüft.


 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()) } } } } /** *    ,    *   IDE,      . */ private fun createFix(): LintFix { return fix().replace().text("setOnClickListener").with("setThrottlingClickListener").build() } } 

Die Registrierung


Das Letzte, was wir tun müssen, ist, Probleme zu unserer Registrierung hinzuzufügen und Lint mitzuteilen, dass es eine spezielle Problemregistrierung gibt, die zusammen mit der Standardregistrierung verwendet werden sollte.


 class MyIssueRegistry : IssueRegistry() { override val issues: List<Issue> = listOf(ISSUE_CLICK_LISTENER) } 

In der build.gradle Modulebene:


 jar { manifest { attributes("Lint-Registry-v2": "co.infinum.lint.MyIssueRegistry") } } 

Dabei ist co.infinum.lint ein Paket der Klasse MyIssueRegistry . Jetzt können Sie die jar Task mit dem gradlew Skript gradlew Die Bibliothek sollte im Verzeichnis build/libs gradlew .


Hier ist ein weiteres Beispiel für eine Lint-Benutzerprüfung, bei der Sie sehen können, wie XML-Dateien verarbeitet werden.


Verwenden Sie


Ihr neuer Lint-Check kann im Projekt verwendet werden. Wenn diese Prüfung auf alle Projekte angewendet werden kann, können Sie sie im Ordner ~/.android/lint (Sie können sie erstellen, wenn sie noch nicht vorhanden ist).


Darüber hinaus können Sie Ihre Prüfung in einem separaten Modul in Ihrem Projekt lintChecks und dieses Modul wie jede andere Abhängigkeit mit der Methode lintChecks .


Lohnt es sich?


Lint ist ein wirklich gutes Werkzeug, das jeder Entwickler verwenden sollte. Es ist sehr hilfreich, potenzielle Probleme mit Ihrem Code frühzeitig erkennen zu können. Obwohl benutzerdefinierte Prüfungen vor allem aufgrund der Komplexität der API nicht einfach zu schreiben sind, lohnen sie sich auf jeden Fall und können Ihnen in Zukunft viel Zeit und Mühe sparen.

Source: https://habr.com/ru/post/de456272/


All Articles