Gallery langsam und stockt zwischendurch

  • Antworten:14
mcfly
  • Forum-Beiträge: 286

07.01.2011, 15:26:40 via Website

Hallo zusammen

Meine Gallery besteht aus Elementen, die jeweils eine Textview und ein runterscaliertes Bitmap enthält.
Wenn man schnell nach rechts oder links scrollt stockt es ziemlich.

Hat jemand ein Tipp wo man da die Performance verbessern könnte. Ich weiss unterdessen, dass es an den runterscalierten Bilder liegt:

Bitmap bm = BitmapFactory.decodeFile(FileList.get(position).toString());
i.setImageBitmap(bm);

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(iGalleryHeight, iGalleryHeight);
params.leftMargin = 0;
params.topMargin = 0;
i.setScaleType(ImageView.ScaleType.FIT_XY);
ll.addView(i, params);

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

07.01.2011, 18:15:52 via Website

In welchem Kontext wird der Code durchlaufen ?

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

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

07.01.2011, 19:30:27 via Website

Skaliere vielleicht nur einmal die Bilder runter und cache sie zwischen. Das sollte es deutlich beschleunigen.

Seid nett zueinander: AndroidPIT-Regeln ;)

Antworten
mcfly
  • Forum-Beiträge: 286

10.01.2011, 22:40:12 via App

Der Kontext : Ich habe einen Adapter, der pro Element ein Bild von der sd Karte liest und dann runterskaliert. Meinst Du das mit Kontext?

Antworten
mcfly
  • Forum-Beiträge: 286

10.01.2011, 22:44:23 via App

Das mit vorscalieren und cachen ist eine gute idee. Ich wiess nur nicht ob das bei mir klappt. Hab schlussendlich etwa 3000 Bilder. Mit cachen meinst Du in ein Array vorgaengig abfuellen, oder?

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

10.01.2011, 23:03:05 via Website

Dann wirst du Sie vorher schon skalieren müssen und ablegen.

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

Antworten
mcfly
  • Forum-Beiträge: 286

11.01.2011, 19:02:57 via App

ok ich versuchs... ...

— geändert am 11.01.2011, 19:05:33

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

11.01.2011, 20:24:52 via Website

Du könntest dir eine Art Preloader basteln. Wenn das zu viel Bilder werden kann der im Hintergrund zB +/- 100 Bilder* in eine Liste halten und wenn du beim Scrollen dem Rand zu nahe kommst, läd er im Hintergrund die nächsten Bilder nach und scaliert sie.

*) 100 nur eine Idee von mir. Den passenden Wert musst du rausfinden.

— geändert am 11.01.2011, 20:26:28

Seid nett zueinander: AndroidPIT-Regeln ;)

Antworten
mcfly
  • Forum-Beiträge: 286

20.01.2011, 20:13:44 via App

vielen dank fuer die Antwort. Genau das habe probiert, aber nicht hingekriegt. Als ich in meinem Adapter die prescaled Bilder gesetzt habe funktionierte das. Beim 2. mal durchlaufen durch die gleichen bilder crashte es. Die Imageview haette schon ein parent , besagt die Fehlermeldbung. Immerhin war es fuer mich ein Test im ersten durchlauf was es performancemaessig bringt. Es bringt praktisch nichts.

Antworten
mcfly
  • Forum-Beiträge: 286

12.02.2011, 09:42:57 via Website

Ich habe jetzt einen Preloader gebaut und er funktioniert auch. Sobald ich zu nahe an den Rand meines Caches komme lädt ein zusätzlicher Thread den Cache mit neuen Bildern nach und baut auf der anderen Seite ab.
Bewege ich mich innerhalb des Bereichs ist die Gallery jetzt tatsächlich viel schneller. Juheee !
Komme ich an den erwähnten Rand ruckelt es aber wieder für 2 Sekunden massiv, weil der Thread nachlädt.
War dieses Verhalten zu erwarten oder mache ich da irgendwas noch falsch ?

Ich hab gelesen dass man anstatt klassische Threads AsyncTasks verwenden soll. Ich nehme an, dass das technisch das gleiche ist, einfach nur besser handelbar , richtig ?

Schönes Wochenende

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

12.02.2011, 11:58:41 via Website

Der macht eine menge mehr, zum einen handhabt er die UI Thread dinge für dich transparent, achte auf die methoden des Async task mal genauer.
Zum einen hat er intern einen static Pool der es erlaubt Threads wieder zu verwenden (nutzt Threadpool, Callable bzw FutureTask was in sehr effectiv mach):

http://google.com/codesearch/p?hl=en&sa=N&cd=2&ct=rc#uX1GffpyOZk/core/java/android/os/AsyncTask.java&q=lang:java%20AsyncTask

Schaut man auf den Code werden wohl max 5 Threads benutzt, wenn der bedarf vorhanden ist. Ich würde deinen Code auf den Async Task umschreiben.
Ausser du hast gründe die in nicht kenne.

— geändert am 12.02.2011, 13:22:32

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

Antworten
mcfly
  • Forum-Beiträge: 286

12.02.2011, 21:04:21 via App

Vielen Dank. Das gibt mir Hoffnung. Ich probiers. Sollte ja schnell umgeschrieben sein.

Antworten
mcfly
  • Forum-Beiträge: 286

13.02.2011, 12:41:16 via Website

Ich habe den Thread in einen AsyncTask umgewandelt. Ich habe leider immer noch das gleiche Verhalten.
In meinem Fall spielts denke ich keine Rolle ob ich den Thread oder AsyncTask verwende. Ich muss ja einfach nur einen Job im Hintergrund ausführen und das Gui gar nicht updaten.
Trotzdem danke. Ich werde in Zukunft auf jedenfall die Asyntasks verwenden. Ich sehe die Vorteile im Allgemeinen.

Ich denke es ist einfach so, dass wenn der Asyntask im Hintergrund läuft um meinen Cache im Voraus zu füllen ist das GUI einfach langsamer und ruckelt.
Oder hat noch jemand einen Tip ? Die Gallery mit dem Cache läuft definitiv schneller, nur während dem Cachen rukelts.

Grüsse

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

13.02.2011, 14:46:09 via Website

Wann legst du den Async Task an ? Der erzeugt threads, die sind Teuer anfangs ...

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

Antworten
mcfly
  • Forum-Beiträge: 286

13.02.2011, 21:00:19 via Website

Ich starte eine neue Instanz, wenn ich dem Rand des Caches nahe komme : ( gc = gallerycacher )

Ich hab nach Deinem Tip probiert eine globale Instanz von BitmapCacheAsyncTask zu erstellen und jeweils diese zu starten ( execute ). Dann crashed das ganze beim 2. Mal.

Hier noch mein Aufruf.


if (gc.benabled){
if ((iPosition-gc.getLoadCachebefore()<gc.getIVonPosition()) && !gc.isCaching()){
//Log.v("CACHE", "Cache neu !!!!!");
// Nach unten wird navigiert
Toast.makeText(cRoot, "Caching ...", Toast.LENGTH_SHORT).show();
gc.setCaching(true);

new BitmapCacheAsyncTask().execute("nachunten");
//bitmapcacheasynctask.execute("nachunten");


Toast.makeText(cRoot, "CacheStats " + gc.getHmCache().size() + " : " + gc.iVonPosition + " : " + gc.iBisPosition, Toast.LENGTH_SHORT).show();

}else if ((iPosition+gc.getLoadCachebefore()>gc.getIBisPosition()) && !gc.isCaching()){
//Log.v("CACHE", "Cache neu !!!!!");
// Es wird nach oben navigiert
Toast.makeText(cRoot, "Caching ...", Toast.LENGTH_SHORT).show();
gc.setCaching(true);

new BitmapCacheAsyncTask().execute("nachoben");
//bitmapcacheasynctask.execute("nachoben");

Toast.makeText(cRoot, "CacheStats " + gc.getHmCache().size() + " : " + gc.iVonPosition + " : " + gc.iBisPosition, Toast.LENGTH_SHORT).show();

}

}

Antworten