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 wurde in das Adaptermodul verschoben
Warum entspricht das Hinzufügen von referenzierten Methoden durch jede Klasse (rot markiert) in den Screenshots nicht der in Apk Analyzer angegebenen Summe?
quelle
Antworten:
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
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:
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 secs
mitN micro secs
ohne diskretes Modul verglichen .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
Bedingungen, unter denen der APK-Analysator eine wichtige Rolle spielt. Referenzierte Methoden
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
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
.dex
Dateien, darunter:.dex
Datei für vollständig integrierte Abhängigkeiten.dex
sDie Abhängigkeitsdatei
.dex
ist eine Integration aller Modul-GradlesSchauen 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.Bei beiden handelt es sich um leere Aktivitäten, bei denen die
1.7k
Anzahl 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 wurdeEin anderer konfiguriert für
Obwohl es sich nur um leere Aktivitäten handelt, verursachte ein minimaler Unterschied in Gradle einen Unterschied in der Anzahl der
1.7k
referenzierten Methoden.Und App Gradle ist
Dies ist nur IDE-Filter nichts anderes. Wenn Sie nur eine
.dex
Datei auswählen, entspricht die Anzahl der Referenzmethoden der Summe der Zeilenanzahl der referenzierten Methoden. Wenn Sie jedoch mehrere.dex
Dateien 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
.dex
Dateien ausgewählt und dann die Gleichheit des Analyzer-Filters.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
Jetzt möchte ich klarstellen, wie sich die Entwicklererfahrung und die Codepflege auf das Endergebnis auswirken. AUCH wenn Ihre APK zentralisierte Abhängigkeiten verwendet
Im obigen Beispiel habe ich die Anzahl der
5.1k
referenzierten 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
.jar
Datei imlibs
Verzeichnis 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 .
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.
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.
quelle
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.
quelle
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.
quelle