AS: 3.5.3; Android Gradle Plugin: 3.5.0; Stopień: 5.6.2;
Zauważyliśmy drastyczny wzrost liczby metod wymienionych w naszej aplikacji po podzieleniu modułu „app” na kilka małych modułów. Dziwne jest jednak to, że dodanie metod referencyjnych dla każdej klasy jest mniejsze niż wspomniana suma w narzędziu Android Apk Analyzer.
Dla celów testowych przeniosłem WebActivity.class z modułu „app” do modułu „adapters” i liczba metod referencyjnych wzrosła o 181 metod.
Podsumowując:
app / WebActivity = 63546 Rzeczywiste metody referencyjne, ale pokazano metody 65394 . adapter / WebActivity = 63543 Rzeczywiste metody referencyjne, ale pokazano 65575 metody .
Zauważyliśmy, że „liczba referencyjnych metod” wzrosła o prawie 10 tys. Po dodaniu / podzieleniu 4 nowych modułów.
Jaki jest dokładny problem?
Jak modularyzacja aplikacji może tak drastycznie zwiększyć liczbę metod, do których się odwołuje?
Poniżej zrzuty ekranu, które zrobiłem z dwóch różnych różnic APK-ów: WebActivity przeniesiono z modułu „aplikacji” do modułu „adaptera” i zwiększono liczbę metod referencyjnych 181:
Przeniesiono WebActivity do modułu „adaptera”
Dlaczego na zrzutach ekranu dlaczego dodawanie metod referencyjnych przez każdą klasę (oznaczonych kolorem czerwonym) nie jest równe sumie podanej w Apk Analyzer?
źródło
Odpowiedzi:
Od dłuższego czasu czytam o wydajności kodu i parametrach strojenia. Rzeczywiście, jednym z moich zainteresowań są programy na Androida.
Najpierw przedstawmy podstawowe lub najważniejsze pojęcia, które pomogą nam znaleźć rozwiązanie.
Jak stwierdził programista Android
W związku z tym moduły mają własne poziomy i zależności . Można je eksplorować w projekcie
Hierarchy Viewer
.W rzeczywistości, modułowość kładzie nacisk na kwestie utrzymania . W przeciwieństwie do Performance Matters, ponieważ modularyzacja ma ten ważny wpływ:
Oto schemat, który nakreśliłem, aby wyjaśnić. Jak widać. Podczas korzystania z modułu dyskretnego, w celu wywołania metody A
2N micro secs
porównuje się go zN micro secs
modułem dyskretnym.To pytanie przyszło mi do głowy, że Metody Referencyjne liczą, co jest związane z Głębokością dziedziczenia?
Odpowiedź brzmi: chociaż użycie modularyzacji zwiększa Metodę referencyjną, ale tak naprawdę nie wpływa to na wydajność aplikacji, a głównym możliwym problemem jest głębokość dziedziczenia, w której w większości przypadków można je pominąć .
Podkreślam, że zwiększona liczba metod referencyjnych w modularyzacji wynika z każdego stopnia modułu i zależności
Warunki, w których wpływ na analizator APK są ważne Metody referencyjne
Oprócz powyższego oficjalnego oświadczenia chcę dodać kolejny warunek, w którym wpływ analizatora APK, który:
ile doświadczenie ma programista w modularyzacji?
modularyzacja jest jak dom, w którym architektura (deweloper) określa, gdzie powinna być kuchnia, a gdzie pokój wypoczynkowy i gdzie powinna być toaleta. Co jeśli architektura zdecyduje się połączyć WC i kuchnię? Tak, to katastrofa.
Może się to zdarzyć podczas modularyzacji, jeśli deweloper nie ma dużego doświadczenia.
Odpowiadanie na pytania OP w uzupełnieniu do dodatkowych informacji
Tutaj odpowiadam na pytania operacyjne w komentarzach
Ponieważ moduły można budować, testować i debugować, MUSZĄ mieć własne poziomy i zależności.
Podczas realizacji projektu wielomodułowego kompilator generuje kilka
.dex
plików, w tym:.dex
plik dla ogółu zintegrowany zależnościami.dex
s.dex
plik zależności to integracja wszystkich stopni modułówSpójrzmy, jak stopień modułu wpływa na ostateczną Liczbę Mothods?
są 2
APK
s z takim samym wynikiem, ale różnica w liczeniu metod referencyjnych.Oba są pustymi działaniami, które mają
1.7k
różnicę w liczbie metod referencyjnych, która jest bardzo wysoka, zależy od ich funkcjonalności. Kluczową różnicą jest stopień ich modułu, do którego skonfigurowano jednego z nichKolejny skonfigurowany do
Chociaż są to tylko puste czynności, ale spowodowana minimalna różnica w Gradle
1.7k
różnicę w referencyjnych metod.A aplikacja Gradle jest
To tylko filtrowanie IDE. na pewno, jeśli wybierzesz tylko
.dex
plik Liczba metod referencyjnych jest równa SUMIE każdego wiersza Liczba referencyjnych metod, ale jeśli wybierzesz wiele.dex
plików, zobaczysz różnicę w SUMIE i rzeczywistej liczbie, która wynika z równości w referencjach, które analizator wolał filtruj je.na zrzutach ekranu wybrałeś wiele
.dex
plików, a następnie równość filtrów w analizatorze.Teoretycznie NIE powinno to zwiększać liczby referencyjnych metod. ALE , jak to wyjaśniłem, Doświadczenie programistów ma duży wpływ na końcowy wynik.
Team Analyzer powinien sprawdzić i naprawić problemy z wydajnością przed podobną wersją
Teraz chcę wyjaśnić, w jaki sposób Doświadczenie programistów i obsługa kodu wpływają na końcowy wynik. NAWET, jeśli Twój pakiet APK korzysta ze scentralizowanych zależności
w powyższym przykładzie zwiększyłem Liczbę
5.1k
Metod Referencyjnych NAWET JEŚLI miałem Centralne Zależności !!!!!Jak to możliwe ?
Odpowiedź brzmi: właśnie dodałem niepotrzebny i ukryty
.jar
plik wlibs
katalogu projektu. tak łatwo, jak widać, wpłynąłem na końcowy wynik.Jak widać Doświadczenie programistów wpływa na wynik końcowy. W rezultacie praktycznie możliwe jest, że metody referencyjne będą się zwiększać, chociaż teoretycznie NIE powinny .
kompilacja nie ma żadnego związku z liczonymi metodami. to zgodne z tym, co programista chce zastosować.
Wniosek
Omówiłem wszystkie możliwości związane z tym problemem. Rzeczywiście, można go wyprowadzić z różnych sytuacji, a programista, korzystając z tych wskazówek, może rozwiązać problem.
WAŻNA UWAGA: prawie wszystkie oświadczenia to moje dochodzenie i badania. w rzeczywistości mogą występować błędy i usterki i zostaną zaktualizowane w celu dodania znacznie więcej informacji w przyszłości.
źródło
Odpowiadając na moje pytanie, ponieważ rozwiązanie właśnie kliknęło mi w głowie, chociaż nie zostało to wypróbowane, ale zadziałałoby, zdecydowanie lub najprawdopodobniej. :) Odpowiedź udzielona przez Mr.AF była bardzo przydatna do osiągnięcia ostatecznego rozwiązania. Mówi o Dlaczego? ale nie jak tego uniknąć lub jak to poprawić.
Oto sposób na odzyskanie oryginalnej / rzeczywistej liczby referencyjnych metod -
Nie zależy to od tego, jak modulizujemy aplikację, ale od tego, jak dodajemy zależności. Jeśli dodamy zależność za pomocą „ implementacji ”, ta zależność pozostanie prywatna dla modułu i żaden inny moduł nie będzie mógł jej użyć. A jeśli dodamy tę samą zależność za pomocą „ api ” (równej przestarzałej „kompilacji”), to stanie się publiczna i inne zależne moduły będą mogły z niej korzystać. Ponieważ używamy „implementacji” do dodawania zależności w każdym module w projekcie wielomodułowym, każdy moduł ma wszystkie wymagane zależności jako samodzielne, dlatego można go skompilować indywidualnie. Powoduje to skrócenie czasu kompilacji / kompilacji, ponieważ kompilowane mogą być tylko zmodyfikowane moduły. Jednak użycie „implementacji” zwiększa liczbę metod, do których istnieje odwołanieponieważ istnieje tak wiele zduplikowanych metod referencyjnych.
Jeśli więc czas kompilacji nie jest twoim problemem, ale liczba metod, o których mowa, to możesz narysować drzewo zależności wszystkich modułów i uniknąć dodawania zduplikowanej zależności, używając „api” w module podstawowym. W ten sposób nawet górny moduł może korzystać z zależności dodanej przez moduł podstawowy, co pozwoli uniknąć duplikatów. Pamiętaj, że wydłużyłoby to czas kompilacji.
Możemy osiągnąć oba, jeśli potrafimy rozróżnić zależności do debugowania i kompilacji wydania . Dodaj wszystkie zależności za pomocą „implementacji” do kompilacji debugowania i dodaj tylko wymagane i zoptymalizowane zależności do kompilacji wersji za pomocą „api” . W ten sposób kompilacja debugowania będzie szybsza, a kompilacja wydań wolniejsza, co jest przystępne.
Uwaga: zaktualizuję tę odpowiedź, gdy wymyślę, jak zapewnić osobne zależności dla debugowania i kompilacji wydania.
źródło
Widzę całą różnicę w twoim pakiecie „com”. Możesz rozwinąć i porównać, które dokładnie klasy się zmniejszyły. Jeśli budujesz z najnowszą wersją R8, może domyślnie usunąć część kodu. Kiedy umieścisz niektóre klasy w module zmniejszającym moduł, nie wiem, czy publiczne klasy / metody można usunąć, czy też muszą zostać w celu użycia w innym module.
źródło