web-dev-qa-db-fra.com

Augmentation du nombre de méthodes référencées après la modularisation de l'application

AS: 3.5.3; Android Plugin Gradle: 3.5.0; Gradle: 5.6.2;

Nous avons observé une augmentation drastique du nombre de méthodes référencées dans notre application après avoir divisé le module "app" en plusieurs petits modules. Mais ce qui est étrange, c'est que l'ajout de méthodes référencées par chaque classe est inférieur au total mentionné dans Android Apk Analyzer Tool.

À des fins de test, j'ai déplacé WebActivity.class du module 'app' vers le module 'adapters' et le nombre de méthodes référencées a été augmenté de 181 méthodes.

Résumer:

app/WebActivity = 63546 Méthodes référencées réelles mais affichant 65394 méthodes. adapter/WebActivity = 63543 Méthodes référencées réelles mais affichant 65575 méthodes.

Nous avons observé que le 'nombre de méthodes référencées' a augmenté de près de 10k après l'ajout/la division de 4 nouveaux modules.

Quel est le problème exact?

Comment la modularisation des applications peut-elle augmenter le nombre de méthodes référencées si fortement?

Voici les captures d'écran que j'ai prises de deux différences différentes pour les fichiers APK uniquement: WebActivity est passé du module `` application '' au module `` adaptateur '' et 181 méthodes référencées ont été augmentées:

WebActivity dans le module 'app' enter image description here

WebActivity déplacé vers le module "adaptateur" enter image description here

Dans les captures d'écran, pourquoi l'ajout de méthodes référencées par chaque classe (marquées en rouge) n'est pas égal au total donné dans Apk Analyzer?

16
Rohit Surwase

Répondre à ma propre question alors que la solution vient juste de cliquer dans mon esprit, bien que cela ne soit pas essayé mais fonctionnerait, certainement ou très probablement. :) Le réponse donnée par Mr.AF a été très utile pour parvenir à une solution finale. Il parle de pourquoi? mais pas comment l'éviter ou comment l'améliorer.

Voici un moyen de récupérer le nombre de méthodes référencées d'origine/réelles -

Cela ne dépend pas de la façon dont nous modularisons l'application, mais de la façon dont nous ajoutons des dépendances. Si nous ajoutons une dépendance en utilisant ' implementation ' alors cette dépendance reste privée au module et aucun autre module ne peut l'utiliser. Et si nous ajoutons la même dépendance en utilisant ' api ' (égal à 'compile' déconseillé) alors elle devient publique et d'autres modules dépendants peuvent l'utiliser. Puisque nous utilisons 'implémentation' pour ajouter des dépendances dans chaque module dans un projet multi-module, chaque module a toutes les dépendances requises comme autonomes, c'est la raison pour laquelle il peut être compilé individuellement. Cela entraîne une diminution du temps de compilation/compilation car seuls les modules modifiés peuvent être compilés. Mais, l'utilisation de 'implémentation' augmente le nombre de méthodes référencées car il existe de nombreuses méthodes référencées en double.

Donc, si le temps de construction ne vous concerne pas mais que le nombre de méthodes référencées l'est, vous pouvez dessiner l'arborescence des dépendances de tous les modules et éviter d'ajouter des dépendances en double en utilisant 'api' dans le module de base. De cette façon, même le module supérieur peut utiliser les dépendances ajoutées par le module de base , ce qui évitera les doublons. N'oubliez pas que cela augmenterait le temps de construction.

Nous pouvons atteindre les deux si nous pouvions distinguer les dépendances pour le débogage et la publication de la version . Ajoutez toutes les dépendances à l'aide de 'implémentation' pour la version de débogage et ajoutez uniquement les dépendances requises et optimisées pour la version de version à l'aide de ' api '. De cette façon, la version de débogage sera plus rapide et la version de version sera plus lente, ce qui est abordable.

Remarque: je mettrais à jour cette réponse une fois que j'aurais compris comment fournir des dépendances distinctes pour le débogage et la version finale.

2
Rohit Surwase

Je lis depuis longtemps sur les performances du code et les paramètres de réglage.En effet, les programmes Android sont l'un de mes centres d'intérêt.

Voyons d'abord les concepts de base ou les plus importants qui nous aident à trouver une solution.

Comme développeur Android a déclaré

le module peut être construit, testé et débogué indépendamment

Par conséquent, les modules ont leurs propres Gradle et dépendances . Vous pouvez les explorer dans le projet Hierarchy Viewer.

En fait, Modularisation l'accent sur Maintenance compte. Contrairement aux performances, la modularisation a cet impact important:

  • Augmentez la profondeur de l'héritage

Voici un diagramme que j'ai tracé pour le rendre clair. Comme vous pouvez le voir.en utilisant un module discret, pour appeler la méthode A, il y a 2N micro secs par rapport à N micro secs sans module discret.

enter image description here

Cette question me vient à l'esprit que Les méthodes référencées comptent ce qui est lié à la profondeur d'héritage?

La réponse est: Bien que l'utilisation de la modularisation augmente les méthodes référencées, mais cela n'affecte pas réellement les performances de l'application et le principal problème possible est Profondeur de l'héritage dans laquelle dans la plupart des cas est ignorable .

Je souligne que l'augmentation des méthodes référencées dans la modularisation est due à chaque module Gradle & Dependencies

Comment la modularisation des applications peut augmenter considérablement le nombre de méthodes référencées?

Conditions dans lesquelles l'analyseur APK d'impact est important Méthodes référencées

Notez également que la minification et la réduction du code peuvent également modifier considérablement le contenu d'un fichier DEX après la compilation du code source.

En plus de la déclaration officielle ci-dessus, je veux ajouter une autre condition dans laquelle l'impact APK analyseur qui est:

Quelle est l'expérience du développeur en modularisation?

la modularisation est comme une maison qui l'architecture (développeur) définit où devrait être la cuisine et où devraient être les toilettes et où devraient être les toilettes. Et si l'architecture décidait de combiner WC et cuisine? Oui, c'est un désastre.

Cela peut se produire lors de la modularisation si le développeur n'est pas très expérimenté.


Répondre aux questions OP en plus des informations supplémentaires

Ici, je réponds aux questions posées dans les commentaires

Pourquoi Gradle séparé ajouterait-il au nombre de méthodes référencées? Et pour les dépendances distinctes, si le résultat final est un fichier APK unique, je ne pense pas que les dépendances en double dans "app" et le module de fonctionnalité ajouteraient au nombre de méthodes référencées.

Parce que les modules peuvent être construits, testés et débogués, ils DOIVENT avoir leurs propres Gradle & Dependencies.

Pendant que le projet multi-module est en cours d'exécution, le compilateur génère plusieurs .dex fichiers comprenant:

  • une .dex fichier pour les dépendances totalement intégrées
  • modules .dexs

dépendances .dex le fichier est une intégration de tous les modules gradles

Voyons comment un module gradle impacte le nombre final de mothods référencés? !

il y a 2 APKs avec le même résultat mais différence dans le nombre de méthodes référencées.

figure 1figure 2

Ce sont deux activités vides qui ont 1.7k la différence dans le nombre de méthodes référencées qui est très élevée dépend de leur fonctionnalité. La différence clé réside dans le Gradle de leur module l'un d'eux a été configuré pour

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
}

Un autre configuré pour

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0-alpha01'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
}

Bien que ce ne soient que des activités vides, mais une différence minimale dans Gradle a provoqué 1.7k différence dans le nombre de méthodes référencées.

Et App Gradle est

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation project(path: ':module')
}

la principale préoccupation est pourquoi l'ajout du nombre de méthodes référencées individuellement est différent du nombre total de méthodes référencées dans Apk Analyzer?

C'est juste IDE ne filtrez rien d'autre. Pour sûr, si vous ne sélectionnez qu'un .dex file Reference Method Counts est égal à SUM de chaque ligne Referenced Method Counts mais si vous sélectionnez plusieurs fois .dex fichiers, vous verrez une différence dans SUM et le nombre réel qu'en raison de l'égalité dans les références, Analyzer a préféré les filtrer.

dans vos captures d'écran, vous avez sélectionné plusieurs .dex fichiers puis égalité du filtre Analyzer.

dans notre projet, nous utilisons un fichier dependencies.gradle centralisé, il n'y a donc aucune chance de version différente. Donc, pensez-vous que même si nous avons un ensemble de dépendances identique/exact et leurs versions dans les modules de fonctionnalité, cela augmentera le nombre de méthodes référencées?

Théoriquement, il devrait [~ # ~] pas [~ # ~] augmenter le nombre de méthodes référencées. [~ # ~ ] mais [~ # ~] , Comme je l'ai expliqué, L'expérience développeur a un impact important sur le résultat final.

Team Analyzer devrait vérifier et corriger les problèmes de performances avant la sortie, comme

  • règles de proguard
  • ressources réduites et réduites
  • androidManifest.xml
  • réglages gradle

Maintenant, je veux clarifier comment l'expérience développeur et la maintenance du code affectent le résultat final. MÊME si votre APK utilise Dépendances centralisées

figure 3

dans l'exemple ci-dessus, j'ai augmenté 5.1k dans le nombre de méthodes référencées MÊME SI j'avais des dépendances centralisées !! !!!

Comment c'est possible?

La réponse est: je viens d'ajouter un _ inutile et caché .jar fichier dans le répertoire libs du projet. aussi simple que vous pouvez le voir, j'ai affecté le résultat final.

Comme vous pouvez le voir L'expérience développeur affecte le résultat final.En conséquence, Pratiquement il est possible que le nombre de méthodes référencées soit augmenté Bien que Théoriquement Devrait [~ # ~] pas [~ # ~ ] .

Et pourquoi il n'y a pas de différence dans le nombre de méthodes référencées lorsque je compile uniquement le module "app" en désactivant la compilation parallèle? Il aurait dû diminuer car seules les dépendances du module "app" auraient été utilisées, non?

la compilation n'a aucun rapport avec les méthodes référencées count.it respecte ce que le développeur veut se conformer.


Conclusion

J'ai couvert toutes les possibilités autour de la question. En effet, il peut être issu de différentes situations et un développeur en utilisant cette directive peut résoudre le problème.

  • J'espère que vous avez trouvé pourquoi les méthodes référencées ont été augmentées et pourquoi dans certains cas, elles pourraient être considérablement augmentées.
  • Les modules ont leurs modules Gradle & Dependencies et de modularisation. par conséquent, ces références de méthode.
  • La modularisation a en fait un impact sur les performances de l'application, mais elle améliore grandement la maintenance de votre application.
  • L'expérience des développeurs en modularisation a également un impact important sur le résultat final.

NOTE IMPORTANTE: presque toutes les déclarations sont mes investigations et recherches. en effet, il peut y avoir des erreurs et des défauts et sera mis à jour afin d'ajouter beaucoup plus d'informations à l'avenir.


9
Mr.AF

Je vois toute la différence dans votre forfait "com". Vous pouvez développer et comparer les classes exactes qui ont été réduites. Si vous construisez avec la dernière R8, il peut supprimer du code par défaut. Lorsque vous placez certaines classes dans un module de réduction, je ne sais pas si les classes/méthodes publiques peuvent être supprimées ou doivent rester pour être utilisées dans un autre module. enter image description here

0
Dmitry Samoylenko