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


16

AS: 3.5.3; Plugin Android 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» au module «adaptateurs» 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 10 000 après l'ajout / la division de 4 nouveaux modules.

Quel est le problème exact?

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

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' entrez la description de l'image ici

WebActivity déplacé vers le module «adaptateur» entrez la description de l'image ici

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?


J'ai créé un problème, vous pouvez le suivre ici issuetracker.google.com/issues/146957168
Rohit Surwase

Réponses:


9

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.

Introduisons d'abord les concepts de base ou les plus importants dans lesquels nous aider à trouver une solution.

Comme l' a déclaré le développeur Android

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

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

En fait, la modularisation met l'accent sur les questions de maintenance . 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, afin d'appeler la méthode A, il est 2N micro secscomparé à N micro secssans module discret.

entrez la description de l'image ici

Cette question me vient à l'esprit que les méthodes référencées comptent ce qui est lié à la profondeur de l'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 la profondeur d'héritage dans laquelle, dans la plupart des cas, elle 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-elle augmenter considérablement le nombre de méthodes référencées?

Conditions dans lesquelles l'impact APK analyseur 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 où 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 d'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 et dépendances.

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

  • un .dexfichier pour les dépendances totalement intégrées
  • modules .dexs

.dexfichier de dépendances est une intégration de tous les modules gradles

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

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

Figure 1 Figure 2

Ce sont deux activités vides qui ont une 1.7kdifférence dans le nombre de méthodes référencées qui est très élevée en fonction de leur fonctionnalité. Leur différence clé est sur 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, une différence minimale dans Gradle a provoqué une 1.7kdiffé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?

Ce n'est rien d'autre que le filtre IDE. à coup sûr, si vous sélectionnez uniquement un .dexfichier, le nombre de méthodes de référence est égal à la somme des nombres de méthodes référencées de chaque ligne, mais si vous sélectionnez plusieurs .dexfichiers, vous verrez une différence dans la somme et le nombre réel qu'en raison de l'égalité dans les références qu'Analyzer a préféré les filtrer.

dans vos captures d'écran, vous avez sélectionné plusieurs .dexfichiers, puis l'é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 le même ensemble de dépendances et leurs versions dans les modules de fonctionnalités, cela augmentera le nombre de méthodes référencées?

Théoriquement, cela ne 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 doit vérifier et résoudre les problèmes de performances avant la sortie, comme

  • règles de proguard
  • ressources réduites et réduites
  • androidManifest.xml
  • paramètres 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 des dépendances centralisées

figure 3

dans l'exemple ci-dessus, j'ai augmenté le nombre 5.1kde 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 .jarfichier inutile et caché dans le libsrépertoire du projet. aussi simple que vous pouvez le voir, j'ai affecté le résultat final.

Comme vous pouvez le voir Expérience Developer affecte result.as finale par conséquent, pratiquement il est possible que les méthodes référencées compte pour augmenter Bien que théoriquement devrait -elle 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 est conforme à 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 Gradle & Dependencies et modules 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 enquêtes 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.



Merci M.AF, j'espérais obtenir la réponse après "Cette question me vient à l'esprit que les méthodes référencées comptent ce qui est lié à la profondeur de l'héritage? La réponse est", mais vous n'avez pas répondu. Pouvez-vous expliquer pourquoi la profondeur de l'héritage augmente le nombre de méthodes référencées? Comme dans notre cas, nous n'avons ajouté aucune couche supplémentaire, mais simplement divisé le module «app». Il y a une chance d'augmenter le nombre de méthodes référencées dans le cas où un module de fonctionnalité accède aux méthodes d'un autre module de fonctionnalité via le module «app», est-ce la raison?
Rohit Surwase

La réponse @RohitSurwase est le reste de la déclaration. La profondeur de l'héritage n'augmente pas les références de méthode, la modularisation faisant cela et la modularisation cuz Profondeur de l'héritage.
Mr.AF

@RohitSurwase, une fonctionnalité accédant à une autre fonctionnalité d'un autre module n'augmente pas vraiment le nombre de méthodes référencées. la principale raison de l'augmentation du nombre de méthodes référencées est Gradle & Dependencies dont chaque module a besoin.
Mr.AF

@RohitSurwase vous donne de bons conseils sur la relation module à module. en fait, si 2 modules ont trop de relations et de méthodes référencées, alors ils doivent être combinés pour de meilleures performances. en fait, le module doit être indépendant dans le terme et le concept.
Mr.AF

1
@RohitSurwase comme je le disais, le pot inutilisé pourrait ne pas être votre cas. et j'ai répertorié toutes les sources possibles dont vous avez besoin pour le rechercher
Mr.AF

2

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. :) La réponse donnée par M.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 « implémentation », 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 à 'compiler' obsolète) alors elle devient publique et d'autres modules dépendants peuvent l'utiliser. Étant donné que 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 «mise en œuvre» augmente le nombre de méthodes référencées car il y a tellement de méthodes référencées en double.

Donc, si le temps de construction n'est pas votre problème 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 version . Ajoutez toutes les dépendances à l'aide de «mise en œuvre» pour la génération de débogage et ajoutez uniquement les dépendances requises et optimisées pour la génération de versions à l'aide de «api» . De cette façon, la génération de débogage sera plus rapide et la version de publication 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.


j'ai aimé les bons matériaux.
Mr.AF

0

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. entrez la description de l'image ici


Oui, j'ai développé et vérifié chaque package, y compris «com». 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?
Rohit Surwase
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.