Android: EditText verursacht Speicherverlust

9

Ich möchte damit beginnen, zu sagen, dass es das erste Mal ist, dass ich mich mit Performance auseinandersetzen muss, weil es das erste Mal ist, dass ich eine Android-App entwickle.

Die App

Die App ist ein Quellcode-Editor, in dem Sie Dateien öffnen, ändern und speichern können. Die App besteht aus 4 Teilen:

  • Die Navigatoransicht: enthält eine ListView für die geöffneten Dateien und eine TreeView für die geöffneten Ordner.
  • Der code views container: Dieser enthält die Ansichten, die den eigentlichen Code enthalten.
  • Der Code-Container: Dies ist eine kleine Ansicht, die eine Textansicht und einen benutzerdefinierten EditText enthält (erstellt von mir, indem ich die EditText-Klasse erweitere, aber noch nicht implementiert ist, so dass sie sich genau wie ein EditText verhält). Das TextView zeigt nur die Codezeilen an.
  • Die offenen und save-Fragmente: Es gibt zwei Fragmente, die ich als DialogFragment benutze: Das save-Fragment ermöglicht es Ihnen, sowohl im lokalen Dateisystem als auch im Dropbox-Dateisystem der verknüpften Konten zu navigieren und die aktuelle Datei zu speichern. Mit dem geöffneten Fragment können Sie durch dieselben Dateisysteme navigieren und eine Datei öffnen.

Das Problem

Nachdem ich den Basiscode-Editor fertiggestellt hatte, wechselte ich zur Syntaxhervorhebung. Nun möchte ich klarstellen, dass die Leaks auch ohne die Syntaxhervorhebung erzeugt werden, also ist das nicht das Problem.

Wie auch immer, indem ich die Syntax highlithing getestet habe, habe ich "große" Dateien (1200 Zeilen Code) geöffnet und festgestellt, dass die App extrem langsam wird, was offensichtlich ist, weil ich den ganzen Text neu formuliere (ich werde das vermeiden) indem Sie nur den sichtbaren Text hervorheben). Das hat mich dazu gedrängt, die App ohne Syntax highlithing mit großen Dateien zu testen und ich stellte fest, dass die App immer noch ein bisschen langsam wurde und ich bemerkte, dass einige Speicherlecks passierten.

Insbesondere, wenn ich eine große Datei (1200 Zeilen Code) öffne, dauert die App 1 Sekunde, um die Zeilen des Codes in der Textansicht anzuzeigen, und wenn ich die Zeichnung des Zeichens tippe, ist es langsam. Außerdem kann jedes Mal, wenn ich ein Zeichen lösche, ein Speicherleck auftreten.

Die Inspektion

Ich habe versucht, den Heap (mit MAT) zu inspizieren, aber wie gesagt, habe ich keine Erfahrung darin und ich bin nicht sicher, was zu tun ist, um dieses Problem zu untersuchen. Es tut mir leid, aber ich kann keine Screenshots hochladen (habe dafür keine Berechtigung von stackoverflow), aber ich kann Ihnen einige Zahlen melden:

System vor dem Öffnen der großen Datei

Systemübersicht

Lecks verdächtigen

Problem 1

Details:

Problem 2

Problem 3

Größte Top-Level-Dominator-Pakete

Größte Objekte

System nach dem Öffnen der großen Datei

Systemübersicht

Lecks verdächtigen:

Problem 1 : Einzelheiten:

Problem 2 :

Problem 3 Problem 4

Größte Top-Level-Dominator-Pakete

Größte Objekte

Vom Android-Gerät Monitor:

System vor dem Öffnen der großen Datei

System nach dem Öffnen der großen Datei

Einige Teile der Zuordnungen:

Vielen Dank im Voraus

BEARBEITEN:

%Vor%

BEARBEITEN

Ok Leute, ich habe das Problem gefunden. Wenn Sie sehen, jedes Mal, wenn ich etwas eintippe, aktualisiere ich die Zeilen EditText und, da der Text lang ist (1200 Zeilen), dauert es eine Weile, um es neu zu berechnen. Habe aber darüber was gemacht! Ich muss einen schnelleren Weg finden, um die Codezeilen anzuzeigen. Eine Option besteht darin, für jede Zeile ein TextView zu verwenden. Auf diese Weise aktualisiere ich nur das TextView, das geändert werden muss. Aber ich weiß nicht, ob 1200 TextView-Objekte schön sind.

%Vor%

BEARBEITEN: Neben der kürzlichen Entdeckung, ohne Syntax-Hervorhebung ist die Typisierung schnell, aber ich stoße immer noch auf Verzögerung, wenn ich die Syntax-Hervorhebung aktiviere.Wenn ich die Datei öffne, ist die Hervorhebung sehr schnell, aber die Eingabe ist immer noch langsam und Speicherleckmeldungen

04-28 04: 49: 58.119: D / dalvikvm (2437): GC_EXPLICIT befreit 185K, 17% frei 6027K / 7244K, pausiert 1ms + 1ms, insgesamt 5ms

erscheint. Wie auch immer, ich frage mich, was ist das Objekt 1-Byte-Array (byte [], boolean []) ist, weil es tatsächlich 2 MB verwendet. Irgendwelche Vorschläge?

BEARBEITEN:

Hat das Problem definitiv gefunden. Da die Datei groß ist und viele Bereiche erstellt werden, muss der Editext die Position aller Bereiche neu berechnen, wenn ich etwas am Anfang der Datei ändere.

    
Christopher A 27.04.2015, 21:01
quelle

1 Antwort

3

Viele andere haben sich mit Ihrem Problem konfrontiert. Hier sind ein paar Hinweise:

von codeninja :

  

Also, was ist die eigentliche Lösung? Vermeiden Sie EditText in einem   RelativeLayout verwenden Sie stattdessen LinearLayout. Laut James, wenn Sie   Schauen Sie sich die DDMS an, viele Neuzeichnungen und Neuberechnungen treten dabei auf   Eingabe des Textes, der sich auf RelativeLayout bezieht. Damit   gibt uns einen Hinweis darauf, dass das Problem in der Tat das RelativeLayoutUpdate ist: I   vergessen zu erwähnen, dass das Setzen eines Fixed mit einem EditText helfen kann   viel mit der Leistung. Es verhindert die Neuberechnung und das erneute Zeichnen von   Layout. Danke an Giorgos Kylafas für den Hinweis in den Kommentaren   Abschnitt unten! Er hat auch Links eingefügt, die für Sie nützlich sein können   es kommt zu Android-Performance-Tipps, also empfehle ich, seinen Kommentar zu lesen.

     

Im ersten Fall ist die Breite von EditText "wrap_content". Jedes Mal, wenn Sie   Ändern Sie den Text, d. h. den Inhalt von EditText, den die Ansicht neu messen muss   und neu Layout, was langsam ist. Insided a enthalten sein   RelativeLayout macht die Dinge noch schlimmer, weil RelativeLayout ist   immer Multi-Pass.

     

Im zweiten Fall ist die Breite von EditText auf "220 dip" festgelegt. Es ist   Mess-und Layout-Pass ist einfach und schnell. Plus Sie verwenden keine   "layout_weight", also ist das übergeordnete LinearLayout Single-Pass.    Ссылка

Von einer anderen Stapelübergabe Frage :

  

Vermeiden Sie die Verwendung von EditText in einem RelativeLayout, verwenden Sie LinearLayout   stattdessen.

Von einer anderen Stapelübergabe Frage :

  

Ich hatte ein ähnliches Problem mit EditText in einem ListView   wurde behoben, indem die EditText-Breite mit gewichteten Breiten auf 0dp geändert wurde   um den Eltern zu entsprechen / füllen.

     Ich weiß nicht genau, warum das passiert ist, aber ich glaube es ist   denn wenn die Breite von EditText so eingestellt ist, dass Inhalte umgebrochen werden, wird dies der Fall sein   passe / zeichne dich selbst so, dass alles passt und der ListView wird   versuche auch, sich neu zu zeichnen, damit alles passt. Also, indem du das gemacht hast   EditText hat eine feste Breite, dieses Redraw wird nicht mehr benötigt.

Zusammenfassend: Achten Sie darauf, die Breite des EditText nicht auf wrap-content zu setzen!

    
Matt 27.04.2015 21:44
quelle

Tags und Links