Anzahl der referenzierten Methoden nach App-Modularisierung erhöht

16

AS: 3.5.3; Android Gradle Plugin: 3.5.0; Gradle: 5,6,2;

Wir haben einen drastischen Anstieg der Anzahl der Methoden festgestellt, auf die in unserer App verwiesen wird, nachdem das App-Modul in mehrere kleine Module aufgeteilt wurde. Das Seltsame ist jedoch, dass die Anzahl der referenzierten Methoden für jede Klasse geringer ist als die im Android Apk Analyzer Tool angegebene Summe.

Zu Testzwecken habe ich WebActivity.class vom Modul 'app' in das Modul 'adapters' verschoben und die Anzahl der referenzierten Methoden um 181 Methoden erhöht.

Zusammenfassen:

app / WebActivity = 63546 Tatsächlich referenzierte Methoden, jedoch mit 65394 Methoden. adapter / WebActivity = 63543 Tatsächlich referenzierte Methoden, jedoch mit 65575 Methoden.

Wir haben beobachtet, dass die Anzahl der referenzierten Methoden nach dem Hinzufügen / Aufteilen von 4 neuen Modulen um fast 10.000 erhöht wurde.

Was ist das genaue Problem?

Wie kann die App-Modularisierung die Anzahl der referenzierten Methoden drastisch erhöhen?

Im Folgenden sind die Screenshots aufgeführt, die ich von zwei verschiedenen APKs gemacht habe. Der einzige Unterschied besteht darin, dass WebActivity vom App-Modul zum Adapter-Modul verschoben und 181 referenzierte Methoden erhöht wurden:

WebActivity im App-Modul Geben Sie hier die Bildbeschreibung ein

WebActivity wurde in das Adaptermodul verschoben Geben Sie hier die Bildbeschreibung ein

Warum entspricht das Hinzufügen von referenzierten Methoden durch jede Klasse (rot markiert) in den Screenshots nicht der in Apk Analyzer angegebenen Summe?

Rohit Surwase
quelle
Ich habe ein Problem erstellt. Sie können es hier verfolgen. Issuetracker.google.com/issues/146957168
Rohit Surwase

Antworten:

9

Ich habe lange über die Codeleistung und die Optimierungsparameter gelesen. Android-Programme sind einer meiner Schwerpunkte.

Lassen Sie uns zunächst die grundlegenden oder wichtigsten Konzepte vorstellen, die uns helfen, eine Lösung zu finden.

Wie Android Developer angegeben hat

Das Modul kann unabhängig erstellt, getestet und getestet werden

Daher haben Module ihre eigenen Gradle & Abhängigkeiten. Und Sie können es im Projekt untersuchen Hierarchy Viewer.

Tatsächlich liegt der Schwerpunkt der Modularisierung auf Wartungsfragen . Im Gegensatz zu Leistungsfragen hat die Modularisierung folgende wichtige Auswirkungen:

  • Vererbungstiefe erhöhen

Hier ist ein Diagramm, das ich gezeichnet habe, um es klar zu machen. Wie Sie sehen können, wird bei Verwendung eines diskreten Moduls zum Aufrufen von Methode A 2N micro secsmit N micro secsohne diskretes Modul verglichen .

Geben Sie hier die Bildbeschreibung ein

Diese Frage ist mir in den Sinn gekommen, dass referenzierte Methoden zählen, was mit der Vererbungstiefe zusammenhängt.

Die Antwort lautet: Obwohl die Verwendung von Modularisierung referenzierten Methods.but erhöht, ist es nicht wirklich die App Leistung auswirken und die Haupt mögliche Problem ist Tiefe der Vererbung , in denen in den meisten Fällen vernachlässigbar .

Ich betone, dass erhöhte referenzierte Methoden in der Modularisierung auf jedes Modul Gradle & Abhängigkeiten zurückzuführen sind

Wie kann die App-Modularisierung die Anzahl der referenzierten Methoden drastisch erhöhen?

Bedingungen, unter denen der APK-Analysator eine wichtige Rolle spielt. Referenzierte Methoden

Beachten Sie auch, dass durch Minimierung und Verkleinerung des Codes auch der Inhalt einer DEX-Datei nach dem Kompilieren des Quellcodes erheblich verändert werden kann.

Zusätzlich zu der obigen offiziellen Erklärung möchte ich eine weitere Bedingung hinzufügen, bei der der APK-Analysator Auswirkungen hat:

Wie viel Erfahrung hat der Entwickler mit Modularisierung?

Modularisierung ist wie ein Zuhause, in dem Architektur (Entwickler) definiert, wo Küche sein soll und wo Ruheraum sein soll und wo WC sein soll. Was ist, wenn sich die Architektur für die Kombination von WC und Küche entscheidet? Ja, das ist eine Katastrophe.

Dies kann während der Modularisierung passieren, wenn der Entwickler nicht sehr erfahren ist.


Beantwortung von OP-Fragen zusätzlich zu zusätzlichen Informationen

Hier beantworte ich op gestellte Fragen in den Kommentaren

Warum sollte ein separater Gradle die Anzahl der referenzierten Methoden erhöhen? Und für separate Abhängigkeiten: Wenn das Endergebnis eine einzelne APK ist, denke ich nicht, dass doppelte Abhängigkeiten in 'App' und Feature-Modul zur Anzahl der referenzierten Methoden beitragen würden.

Da Module erstellt, getestet und debuggt werden können, MÜSSEN sie ihre eigenen Gradle & Dependencies haben.

Während das Projekt mit mehreren Modulen ausgeführt wird, generiert der Compiler mehrere .dexDateien, darunter:

  • eine .dexDatei für vollständig integrierte Abhängigkeiten
  • Module .dexs

Die Abhängigkeitsdatei .dexist eine Integration aller Modul-Gradles

Schauen wir uns an, wie sich ein Modulgradle auf die endgültige Anzahl der referenzierten Motten auswirkt.

Es gibt 2 APK s mit dem gleichen Ergebnis, aber der Unterschied in der Anzahl der referenzierten Methoden.

Abbildung 1 Figur 2

Bei beiden handelt es sich um leere Aktivitäten, bei denen die 1.7kAnzahl der referenzierten Methoden sehr hoch ist und die von ihrer Funktionalität abhängt. Der Hauptunterschied liegt im Gradle ihres Moduls, für den einer von ihnen konfiguriert wurde

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

Ein anderer konfiguriert für

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

Obwohl es sich nur um leere Aktivitäten handelt, verursachte ein minimaler Unterschied in Gradle einen Unterschied in der Anzahl der 1.7kreferenzierten Methoden.

Und App Gradle ist

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')
}

Hauptanliegen ist, warum sich das Hinzufügen einer individuell referenzierten Methodenanzahl von der Gesamtzahl der referenzierten Methoden in Apk Analyzer unterscheidet.

Dies ist nur IDE-Filter nichts anderes. Wenn Sie nur eine .dexDatei auswählen, entspricht die Anzahl der Referenzmethoden der Summe der Zeilenanzahl der referenzierten Methoden. Wenn Sie jedoch mehrere .dexDateien auswählen , werden Sie Unterschiede in der Summe und der tatsächlichen Anzahl feststellen, die aufgrund der Gleichheit der Referenzen, die Analyzer bevorzugt hat filtern Sie sie.

In Ihren Screenshots haben Sie mehrere .dexDateien ausgewählt und dann die Gleichheit des Analyzer-Filters.

In unserem Projekt verwenden wir die zentralisierte Datei dependencies.gradle, sodass keine Chance auf eine andere Version besteht. Denken Sie also, selbst wenn wir dieselben / exakten Abhängigkeiten und deren Versionen in Feature-Modulen haben, wird dies die Anzahl der referenzierten Methoden erhöhen?

Theoretisch sollte es NICHT die Anzahl der referenzierten Methoden erhöhen. ABER , wie ich es erklärt habe, wirkt sich Developer Experience stark auf das Endergebnis aus.

Team Analyzer sollte Leistungsprobleme vor der Veröffentlichung wie prüfen und beheben

  • Proguard Regeln
  • geschrumpfte und minimierte Ressourcen
  • androidManifest.xml
  • Gradle-Einstellungen

Jetzt möchte ich klarstellen, wie sich die Entwicklererfahrung und die Codepflege auf das Endergebnis auswirken. AUCH wenn Ihre APK zentralisierte Abhängigkeiten verwendet

Figur 3

Im obigen Beispiel habe ich die Anzahl der 5.1kreferenzierten Methoden erhöht, AUCH WENN ich zentralisierte Abhängigkeiten hatte !!!!!

Wie ist es möglich?

Die Antwort lautet: Ich habe gerade eine nutzlose und versteckte .jarDatei im libsVerzeichnis des Projekts hinzugefügt . genauso einfach wie du sehen kannst habe ich das Endergebnis beeinflusst.

Wie Sie sehen können, wirkt sich die Entwicklererfahrung auf das Endergebnis aus. Infolgedessen ist es praktisch möglich, dass die Anzahl der referenzierten Methoden erhöht wird, obwohl dies theoretisch NICHT der Fall sein sollte .

Und warum gibt es keinen Unterschied in der Anzahl der referenzierten Methoden, wenn ich nur das App-Modul kompiliere, indem ich die parallele Kompilierung deaktiviere? Es hätte abnehmen sollen, da nur die Abhängigkeiten des 'App'-Moduls verwendet worden wären, oder?

Die Kompilierung hat keine Beziehung zu den Anzahl der referenzierten Methoden. Sie entspricht den Anforderungen des Entwicklers.


Fazit

Ich habe alle Möglichkeiten rund um das Thema abgedeckt. In der Tat kann es aus verschiedenen Situationen hervorgehen, und ein Entwickler kann das Problem mithilfe dieser Richtlinie beheben.

  • Ich würde hoffen, dass Sie herausgefunden haben, warum die referenzierten Methoden erhöht wurden und warum sie in einigen Fällen drastisch erhöht werden könnten.
  • Module haben ihre Module Gradle & Dependencies und Modularisierung erhöhen. daher diese Methodenreferenzen.
  • Die Modularisierung wirkt sich zwar ignorierbar auf die App-Leistung aus, verbessert jedoch die App-Wartung erheblich.
  • Die Erfahrung der Entwickler in der Modularisierung wirkt sich auch stark auf das Endergebnis aus.

WICHTIGER HINWEIS: Fast alle Aussagen sind meine Untersuchungen und Forschungen. In der Tat kann es zu Fehlern und Fehlern kommen, die aktualisiert werden, um in Zukunft viel mehr Informationen hinzuzufügen.


Mr.AF
quelle
Vielen Dank, Herr AF, ich hatte gehofft, die Antwort zu erhalten, nachdem "Diese Frage ist mir in den Sinn gekommen, dass referenzierte Methoden zählen, was mit der Vererbungstiefe zusammenhängt? Die Antwort lautet", aber Sie haben das nicht beantwortet. Können Sie bitte erläutern, warum die Vererbungstiefe die Anzahl der referenzierten Methoden erhöht? Wie in unserem Fall haben wir keine zusätzliche Ebene hinzugefügt, sondern nur das 'App'-Modul aufgeteilt. Es besteht die Möglichkeit, dass sich die Anzahl der referenzierten Methoden erhöht, wenn ein Feature-Modul über das App-Modul auf Methoden eines anderen Feature-Moduls zugreift. Ist dies der Grund?
Rohit Surwase
Die Antwort von @RohitSurwase ist der Rest der Anweisung. Die Vererbungstiefe erhöht nicht die Methodenreferenzen, die Modularisierung und die Modularisierung, da die Vererbungstiefe.
Mr.AF
@RohitSurwase, eine Funktion, die auf eine andere Funktion in einem anderen Modul zugreift, erhöht die Anzahl der referenzierten Methoden nicht in hohem Maße. Der Hauptgrund für die Erhöhung der Anzahl der referenzierten Methoden ist Gradle & Dependencies, die jedes Modul benötigt.
Mr.AF
@RohitSurwase Sie zeigen gute Tipps zur Beziehung von Modul zu Modul. Wenn 2 Module zu viele Beziehungen und referenzierte Methoden haben, sollten sie für eine bessere Leistung kombiniert werden. Eigentlich muss das Modul in Bezug auf Begriff und Konzept unabhängig sein.
Mr.AF
1
@RohitSurwase, wie ich sagte, unbenutztes Glas ist möglicherweise nicht Ihr Fall. Etwas, das ich meine, ist Entwicklererfahrung und es ist möglich, dass die Möglichkeit aus verschiedenen Quellen hervorgeht. und ich habe alle möglichen Quellen aufgelistet, die Sie brauchen, um es zu durchsuchen
Mr.AF
2

Die Beantwortung meiner eigenen Frage als Lösung hat mir gerade in den Sinn gekommen, obwohl dies nicht versucht wird, aber definitiv oder höchstwahrscheinlich funktionieren würde. :) Die Antwort von Mr.AF war sehr nützlich, um eine endgültige Lösung zu finden. Es geht um Warum? aber nicht, wie man es vermeidet oder wie man das verbessert.

Hier ist eine Möglichkeit, die Anzahl der ursprünglich / tatsächlich referenzierten Methoden wiederherzustellen -

Es hängt nicht davon ab, wie wir die App modularisieren, sondern davon, wie wir Abhängigkeiten hinzufügen. Wenn wir eine Abhängigkeit mithilfe von ' Implementierung ' hinzufügen , bleibt diese Abhängigkeit für das Modul privat und kann von keinem anderen Modul verwendet werden. Und wenn wir dieselbe Abhängigkeit mit ' api ' hinzufügen (gleich veralteter 'compile'), wird sie öffentlich und andere abhängige Module können sie verwenden. Da wir 'Implementierung' verwenden, um Abhängigkeiten in jedem Modul in einem Projekt mit mehreren Modulen hinzuzufügen, hat jedes Modul alle erforderlichen Abhängigkeiten als in sich geschlossen. Aus diesem Grund kann es einzeln kompiliert werden. Dies führt zu einer kürzeren Erstellungs- / Kompilierungszeit, da nur geänderte Module kompiliert werden können. Die Verwendung von 'Implementierung' erhöht jedoch die Anzahl der referenzierten Methoden da es so viele doppelt referenzierte Methoden gibt.

Wenn die Erstellungszeit nicht Ihr Anliegen ist, sondern die Anzahl der referenzierten Methoden, können Sie den Abhängigkeitsbaum aller Module zeichnen und das Hinzufügen doppelter Abhängigkeiten vermeiden, indem Sie 'api' im Basismodul verwenden. Auf diese Weise kann auch das Top-Modul die vom Basismodul hinzugefügte Abhängigkeit verwenden, wodurch Duplikate vermieden werden. Denken Sie daran, dies würde die Erstellungszeit verlängern.

Wir können beides erreichen, wenn wir Abhängigkeiten für Debug- und Release-Build unterscheiden können . Fügen Sie alle Abhängigkeiten mithilfe von 'Implementierung' für die Debug- Erstellung hinzu und fügen Sie mithilfe von 'API' nur die erforderlichen und optimierten Abhängigkeiten für die Release-Erstellung hinzu . Auf diese Weise wird der Debug-Build schneller und der Release-Build langsamer, was erschwinglich ist.

Hinweis: Ich würde diese Antwort aktualisieren, sobald ich herausgefunden habe, wie separate Abhängigkeiten für Debug- und Release-Build bereitgestellt werden können.

Rohit Surwase
quelle
Ich mochte es. Gute Materialien.
Mr.AF
0

Ich sehe den Unterschied in Ihrem 'com'-Paket. Sie können erweitern und vergleichen, welche genauen Klassen verkleinert wurden. Wenn Sie mit dem neuesten R8 erstellen, kann standardmäßig Code entfernt werden. Wenn Sie einige Klassen in den Modul-Shrinker einfügen, wissen Sie nicht, ob öffentliche Klassen / Methoden entfernt werden können oder für die Verwendung in einem anderen Modul verbleiben müssen. Geben Sie hier die Bildbeschreibung ein

Dmitry Samoylenko
quelle
Ja, ich habe jedes Paket einschließlich 'com' erweitert und überprüft. Das Hauptproblem ist, warum sich das Hinzufügen einer individuell referenzierten Methodenanzahl von der Gesamtzahl der referenzierten Methoden in Apk Analyzer unterscheidet.
Rohit Surwase