onTextChanged zu langsam?

  • Antworten:11
Gelöschter Account
  • Forum-Beiträge: 2.492

04.04.2014, 14:09:06 via Website

Hallo,

ich habe auf meinem EditText einen TextChangedListener und in der Methode onTextChanged() Methode, färbe ich einmal je nach Eingabe die Buchstaben in einem TextView rot oder grün (mit einem SpannableStringBuilder) und wenn eine Leertaste abgefangen wird leere ich das EditText mit setText("");
Das sind mit allem drum und dran knapp 90 Zeilen. Wenn man den Text jetzt beim Testen recht schnell eingibt hängt die Eingabe ein bisschen.
(Das TextView und EditText habe ich alles schon auf match_parent gesetzt, damit das nicht immer neu generiert werden muss)
Kann ich das alles noch ein bisschen "performanter" gestalten, also das das nicht so stark hängt, wenn man Text schnell eingibt.

Wenn es gewünscht ist kann ich auch den Code posten ist aber halt recht viel ;)

Antworten
Fabian Simon
  • Forum-Beiträge: 359

04.04.2014, 14:16:10 via Website

Hi,
code wäre nicht verkehrt.
Jedoch ist glaub ich nur der Code der onTextChange methode interesannt um mehr Performence zu erhalten

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.04.2014, 14:30:47 via Website

Okay hier alles aus der onTextChanged:
1@Override
2 public void onTextChanged(CharSequence eingabeText, int arg1, int arg2, int arg3) {
3 // TODO Auto-generated method stub
4//Die Zeit startet wenn das erste Mal geklickt wurde (und kein Orientation Wechsel vorliegt)
5 if(!gestartet){
6 if(!eingabeText.toString().contentEquals("")){
7 SpielStart();
8 gestartet = true;
9 eingabe.setHint("");
10 }
11 }
12
13 orientwechsel = false;
14 bisherRichtigStr = "";
15 falscherBuchstabe = false;
16 WortbeiEingabe = eingabeText.toString();
17 letzterBuchstabe = 0;
18 if(WortbeiEingabe.length() > 0){
19 tempWort = WortbeiEingabe.substring(WortbeiEingabe.length() - 1);
20 letzterBuchstabe = tempWort.charAt(0);
21 } else if(WortbeiEingabe.length() == 0){//Wenn kein Text im EditText steht
22 builder.clear();
23//das erste Wort wird schwarz gemacht (es gab sonst Probleme auf einem alten Samsung)
24 SpannableString erstesWort = new SpannableString(AusgabeListe.get(0) + " ");
25 erstesWort.setSpan(new ForegroundColorSpan(Color.BLACK), 0, erstesWort.length(), 0);
26 builder.append(erstesWort);
27 for(int j = 1; j < 12; j++){
28 builder.append(AusgabeListe.get(j) + " ");//die restlichen 11 Wörter werden angehängt
29 }
30 ausgabe.setText(builder, BufferType.SPANNABLE);
31 }
32
33 if(letzterBuchstabe != ' '){//Wenn das letzte eingegebene kein Leerzeichen ist
34 for(int i = 0; i < WortbeiEingabe.length(); i++){
35 if(WortbeiEingabe.length() <= AusgabeListe.get(0).length()){
36//Wenn der Buchstabe an Stelle i = ist mit dem im TextView
37 if(WortbeiEingabe.charAt(i) == AusgabeListe.get(0).charAt(i)){
38 if(!falscherBuchstabe){//wenn kein falscher Buchstabe vorhanden ist
39 builder.clear();
40 SpannableString richtig = new SpannableString(String.valueOf(WortbeiEingabe.substring(0, WortbeiEingabe.length())));
41//das Wort wird Grün gemacht wenn es richtig ist
42 richtig.setSpan(new ForegroundColorSpan(Color.GREEN), 0, richtig.length(), 0);
43 builder.append(richtig);//das Wort wird hintugefügt
44//Wenn das Wort nocht nicht so lang ist wie das im TextView
45 if(richtig.length() < AusgabeListe.get(0).length()){
46//der Rest des Wortes wird hinzugefügt
47 builder.append(AusgabeListe.get(0).substring(richtig.length(), AusgabeListe.get(0).length()));
48 }
49 for(int j = 0; j < 12; j++){
50 builder.append(" " + AusgabeListe.get(j+1));//der Rest des Textes wird hinzugefügt
51 }
52 ausgabe.setText(builder, BufferType.NORMAL);
53 }
54 } else if(WortbeiEingabe.charAt(i) != AusgabeListe.get(0).charAt(i)){
55 falscherBuchstabe = true;
56 SpannableString letztesWort = new SpannableString(AusgabeListe.get(0));
57//das Wort wird rot gemacht
58 letztesWort.setSpan(new ForegroundColorSpan(Color.RED), 0, letztesWort.length(), 0);
59 builder.clear();
60 builder.append(letztesWort);//das rote Wort wird hinzugefügt
61 builder.append(" ");
62 for(int j = 0; j < 12; j++){
63 builder.append(AusgabeListe.get(j+1) + " ");//der Rest des Textes wird hinzugefügt
64 }
65 ausgabe.setText(builder, BufferType.NORMAL);
66 }
67 } else {
68 falscherBuchstabe = true;
69 SpannableString letztesWort = new SpannableString(AusgabeListe.get(0));
70//das Wort wird rot gemacht
71 letztesWort.setSpan(new ForegroundColorSpan(Color.RED), 0, letztesWort.length(), 0);
72 builder.clear();
73 builder.append(letztesWort);//das rote Wort wird hinzugefügt
74 builder.append(" ");
75 for(int j = 0; j < 12; j++){
76 builder.append(AusgabeListe.get(j+1) + " ");//der Rest des Textes wird hinzugefügt
77 }
78 ausgabe.setText(builder, BufferType.NORMAL);
79 }
80 }
81 }
82
83 if(letzterBuchstabe == ' '){//Wenn das letzte eingegebene ein Leerzeichen ist
84 anschläge = anschläge + AusgabeListe.get(0).length() + 1;
85 wörter++;
86//Wenn das Eingegebene Wort = das Wort im TextView ist
87 if(WortbeiEingabe.substring(0, WortbeiEingabe.length()-1).contentEquals(AusgabeListe.get(0))){
88 richtigeWörter++;//Richtige Wörter hochzählen
89//Bisherige richtigeAnschläge + Das Wort + Leerzeichen
90 richtigeAnschläge = richtigeAnschläge + AusgabeListe.get(0).length() + 1;
91 }
92 AusgabeListe.remove(0);//Das erste Wort in der Ausgabe wird gelöscht
93 if(AusgabeListe.size() < 50){
94 zufall = random.nextInt(WortListe.size());//Eine zufällige Zahl wird generiert
95 AusgabeListe.add(WortListe.get(zufall));
96 }
97 eingabe.setText("");//Das eingabeFeld wird leer gemacht
98 }

— geändert am 04.04.2014, 14:34:31

Antworten
Fabian Simon
  • Forum-Beiträge: 359

04.04.2014, 14:43:36 via Website

Also....
Nummer 1 : (Machts vielleicht nicht schneller, aber übersichlicher.)

Lagerere Codeteile die du öfters nutzt in eine eigenen Klasse aus!
z.B.:
1falscherBuchstabe = true;
2 SpannableString letztesWort = new SpannableString(AusgabeListe.get(0));
3//das Wort wird rot gemacht
4 letztesWort.setSpan(new ForegroundColorSpan(Color.RED), 0, letztesWort.length(), 0);
5 builder.clear();
6 builder.append(letztesWort);//das rote Wort wird hinzugefügt
7 builder.append(" ");
8 for(int j = 0; j < 12; j++){
9 builder.append(AusgabeListe.get(j+1) + " ");//der Rest des Textes wird hinzugefügt
10 }
11 ausgabe.setText(builder, BufferType.NORMAL);

Dann schrumpfen deine 90 Zeilen gewaltig.

Nummer 2 : "Rollen"(>>) sind immer schneller als schleifen aber ich denke das fällt hier nicht ins gewicht.
Du könntest dir auch noch überlegen, ob du das ganze nicht in einen anderen Thread auslagerst und dann nur das ergebnis Anwedest, wenn es vorhanden ist.

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.04.2014, 14:54:53 via Website

Nummer 1: habe ich gemacht.
Nummer 2: Was ist/sind Rollen? Habe ich ehrlich gesagt noch nie gesehen

Wenn man einen neuen Thread startet habe ich gelesen, dass dann jedes mal ein neuer Thread gestartet wird und das würde das System dann ja komplett auslasten, oder kann man so ein Thread am Ende wieder beenden?

Antworten
Fabian Simon
  • Forum-Beiträge: 359

04.04.2014, 15:06:36 via Website

Vergiss das mit dem Role.
Ja natürlich.
Ich komm aus der Java Welt deshalb kann ich es dir auch damit am besten erklären...

Also es gibt ja eine Klasse Thread.
Von dieser Kannst du Erben.

1public class MachWasGesondert extends Thread{
2//musst du ueberschreiben.
3public void run(){
4//Das passiert in dem extra thread
5}
6
7
8}
9
10public static void main(String[] args){
11 MachWasGesondert machwas = new MachWasGesondert();
12 machwas.start();//um den neuen Thread zu starten
13}

Sobald die Methode run endet, stribt der Thread.

Jedoch würde ich in deinem Fall nur eine Threadobejct erzeugen, das vorsich hinrennt.
Diese Bekommt dann per Event informationen die sie verarbeiten soll, sobald diese vorhanden sind.

Hoffe du verstehst was ich mein...

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.04.2014, 15:15:55 via Website

Also mache ich eine neue Klasse mit meinem eigenen Thread.
In der onTextChanged rufe ich die Klasse dann jedes mal auf, oder einmal am Anfang und dann läuft die die ganze Zeit?

— geändert am 04.04.2014, 15:28:14

Antworten
Fabian Simon
  • Forum-Beiträge: 359

04.04.2014, 15:35:04 via Website

Du inizialisierst die Klassen in der OnCreate mehtode.
In Onchange gibst nur die Geändert informationen an den thread.
Dieser Verarbeitet diese dann und stellt das ergebnis da.

Achtung bevor du was an der View bzg. am Textfeld ändern kannst musst du wieder zum haupthread wechseln sonst wirft er fehler.
Das machst du mit :
1handler.post(new Runnable() {
2
3 @Override
4 public void run() {
5 //Mach was in Haupthread
6 }
7 });
Den Handler kannst du in der Aktivity erstellen mit
1new Handler()


Bedenke aber das du am ende den Thread auch wieder beenden muss !

— geändert am 04.04.2014, 15:49:37

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.04.2014, 15:55:02 via Website

Also muss ich keine neue Klasse dafür erstellen?
Sondern erstelle diesen Thread in der onCreate?

— geändert am 04.04.2014, 15:57:00

Antworten
Fabian Simon
  • Forum-Beiträge: 359

04.04.2014, 16:05:07 via Website

Doch die Threadklasse brauchst du schon....


Kleines Beispiel:

1public class MeinThread extends Thread{
2 private Handler mainLoop = null;
3 private boolean close = false;
4 private String text = null;
5 public void start(Handler mainLoop){
6 this.mainLoop = mainLoop;
7}
8
9private void verarbeite(String text){
10 //Mach deine Anpassungen
11mainLooppost(new Runnable() {
12 @Override
13 public void run() {
14 //Mach was in Haupthreat
15 }
16 });
17text = null;
18}
19
20public void setText(String text){
21 this.text = text;
22}
23public void run(){
24 while(!colse){
25 while (text == null) Thread.sleep(100);
26 verarbeite(text);
27}
28
29public void CloseIt(){
30 colse = true;
31}
32}
33
34}


So in etwa und dann in der Activity :

1public class meineA extends Activity{
2private MeinThread mT = null;
3 public void onCreate(...){
4 mT = new MeinThread();
5 mt.start(new Handler())
6}
7
8...
9
10public void onChange(){
11 mt.setText("der text");
12}
13}

Code hab ich jetzt dirket eingetippt aber der Weg sollte klar sein denk ich .

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.04.2014, 17:05:42 via Website

Hab das jetzt so ausprobiert, aber es hängt leider wenn überhaupt nur ganz bisschen weniger.

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

04.04.2014, 20:16:31 via Website

Ähnliches habe Ich auch schon mich mal gefragt. Beim durchsuchen einer ListView, es scheint als ob irgendwo einen art "throttle" sitzt die keiner wirklich zu kennen scheint. Allerdings ist mein szenario anders und ich nutze das Filter Interfaceface was die sache mit dem Thread obsolete macht

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten