Ladebild/Ladescreen bei Klick auf Button (onClickListener)

  • Antworten:12
Robert H.
  • Forum-Beiträge: 7

12.02.2012, 19:12:57 via Website

Hallo Leute,

ich habe schon viel gesucht und leider nichts gefunden.

Entweder weil es das Ergebnis noch nicht gibt, oder weil ich die falschen Begriffe gesucht habe.

Was ich vorhabe ist eigentlich recht simpel.

Wenn ich auf einen Button mit einem onClickListener klicke, verweist dieser auf eine Funktion, welche etwas längere Zeit beansprucht. So etwa 5-7 Sekunden.

Wie erreiche ich nun, dass während dieser Zeit ein Ladebild, bzw. Ladescreen oder Layout angezeigt wird?

Sobald ich auf den Button klicke "friert" der Screen ein, bis die gesamte Funktion geladen wurde.

Auch wenn ich vor dem Aufruf der Funktion, beispielsweise ein Toast setze, wird das erst nach dem Laden aufgerufen.

Veränder ich den ContentView vor dem Aufruf der Funktion, wird dieser auch erst nach dem Laden der Funktion dargestellt.

Ich weiß leider im Moment nicht weiter.

Wenn ihr noch welche Informationen braucht, schreibt mir bitte.

mfg

Robert

Antworten
Daniel online
  • Forum-Beiträge: 282

12.02.2012, 19:19:58 via Website

Lade deine Funktion am besten in einem eigenen Thread.
Dann läuft der Ui-Thread weiter und du kannst dort ein Ladebildschirm anzeigen.

Google einfach mal danach, solltest recht schnell was finden.

mfg,
Daniel

Antworten
Robert H.
  • Forum-Beiträge: 7

12.02.2012, 19:59:16 via Website

Danke für deine Antwort.

Ich habe folgendes probiert und habe es scheinbar noch nicht richtig verstanden:
1auswahl_button.setText("Laden...");
2new Thread(new Runnable() {
3 public void run() {
4 plan_anzeige(daten_klasse, daten_datum, datum_auswahl, datum_international);
5 }
6 }).start();
Leider ändert er kurz den Text und stürzt dann sofort ab. (Sorry...)
Lasse ich die run() Methode leer, dann stürzt er nicht ab und ändert den Button Text.
Weiter passiert natürlich nichts, ist ja auch dann nichts weiter eingetragen.

Aber so wie ich es bisher habe gehts leider noch nicht.

Vielleicht kannst du mir noch einen kleinen Denkanstoß geben.

mfg

Robert

Antworten
Felix
  • Forum-Beiträge: 259

12.02.2012, 22:24:54 via Website

Tach!

Probier es mal lieber mit dem einfacheren AsyncTask. Die Kommunikation zwischen Thread ist kein leichtes Unterfangen. AsyncTask nimmt dir die meiste Arbeit diesbezüglich ab.


Felix.

Antworten
Robert H.
  • Forum-Beiträge: 7

14.02.2012, 11:12:51 via Website

Danke für deine Antwort!

Ich habe nun folgendes ausprobiert.

Leider stürzt die App dadurch auch ab. Was habe ich hier falsch gemacht?


1new AsyncTask() {
2 protected Void doInBackground(Void... params) {
3 plan_anzeige(daten_klasse, daten_datum, datum_auswahl, datum_international);
4 return null;
5 }
6
7
8 protected void onPostExecute(Void result) {
9 if (!isFinishing()) {
10 auswahl_button.setText("Laden...");
11 }
12 super.onPostExecute(result);
13 }
14
15 @Override
16 protected Object doInBackground(Object... arg0) {
17 throw new UnsupportedOperationException("Not supported yet.");
18 }
19}.execute();

mfg

Robert

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

14.02.2012, 11:20:04 via Website

Du schmeisst doch in Zeile 17 selbst die Exception, die zum Absturz führt :)
Guck dir nochmal genau an wie man Async Tasks aufbaut. Vor allem sollte er nur EINE doInBackground Methode haben, dann aber mit der richtigen Methodensignatur.

— geändert am 14.02.2012, 11:21:19

Antworten
Robert H.
  • Forum-Beiträge: 7

14.02.2012, 12:11:11 via Website

Ich arbeite gerade an dem Problem und ich habe dabei bei den Abstürzen immer das Problem zu erkennen, was den Absturz verursacht hat.

Wie komme ich an die Exceptions die geworfen werden? Ich sehe immer nur "Sorry...force close". Das hilft mir immer nicht weiter.

Ich habe mal versucht über die Konsole an irgendwelche Logs ranzukommen. Jedoch kommt dort immer "Permission denied".

Vielleicht könnt ihr mir da ja einen Tipp geben. Danke!

mfg

Robert

Antworten
Robert H.
  • Forum-Beiträge: 7

14.02.2012, 12:51:45 via Website

Danke, das habe ich gesucht.

Nutze zwar NetBeans, aber das hat die Funktion auch.

Dann habe ich da gleich eine Frage zu. Ich habe den Async Task nun in eine Klasse verlegt, die wie folgt aussieht:

1private class PlanLaden extends AsyncTask<Void, Integer, Void> {
2 @Override
3 protected void onPostExecute(Void result) {
4 setContentView(R.layout.plan_anzeige);
5 zurueck = R.layout.logged_in;
6 }
7
8 @Override
9 protected void onPreExecute() {
10 auswahl_button.setText("Laden...");
11 }
12
13 @Override
14 protected Void doInBackground(Void... params) {
15 plan_anzeige(daten_klasse, daten_datum, datum_auswahl, datum_international);
16 return null;
17 }
18 }

Den Aufruf mache ich mit: new PlanLaden().execute();

Jetzt bekomm ich folgenden Fehler:
java.lang.RuntimeException: An error occured while executing doInBackground()
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Was bedeutet dieser Fehler? Rufe ich Looper.prepare() in doInBackground() auf, so kommt eine NullPointerException.

mfg

Robert

Antworten
Robert H.
  • Forum-Beiträge: 7

14.02.2012, 16:03:37 via Website

Nachdem ich alles aus plan_anzeige auskommentiert oder entfernt habe, was meiner Ansicht nach auf die Oberfläche zugreift, besteht das Problem weiterhin.

Hier ist nun der Rest von plan_anzeige:

[code]
JSON stunden = new JSON("SELECT stunden FROM infopoint_dig_stunden WHERE position='" + daten_klasse.sql("position", false) + "'", pfad);
int stunden_anzahl = Integer.parseInt(stunden.sql("stunden", false));
String[] stunden_inhalt = new String[stunden_anzahl + 2];
int sortieren_min_ein = Integer.parseInt(daten_klasse.sql("sortieren", false)) - 1;
int position = Integer.parseInt(daten_klasse.sql("position", false));
String zelle = null;
JSON hole_plan = new JSON("SELECT * FROM infopoint_dig_plaene WHERE datum='" + datum_international + "'", pfad);
for (int s = 1; s < stunden_anzahl + 1; s++) {
if (position == 0) {
zelle = s + "_" + sortieren_min_ein + "o";
} else {
zelle = s + "_" + sortieren_min_ein + "u";
}
if (hole_plan.sql(zelle, false).equals("")) {
stunden_inhalt[s] = "";
} else {
stunden_inhalt[s] = hole_plan.sql(zelle, false);
}
}
String inhalt_dar = null;
boolean mehrere_std = false;
int mehrere_stunden = 0;
String stunde = null;
boolean rotfarbig;
String erg = "";
ArrayList<String> stunden_val = new ArrayList<String>();
ArrayList<String> inhalt_dar_org = new ArrayList<String>();
for (int s = 1; s < stunden_anzahl + 1; s++) {
inhalt_dar = "";
mehrere_std = false;
rotfarbig = false;
inhalt_dar = stunden_inhalt[s];
if (inhalt_dar.length() >= 19 && inhalt_dar.substring(inhalt_dar.length() - 18).equals("--zellenverbindung")) {
mehrere_stunden = s + Integer.parseInt(inhalt_dar.substring(inhalt_dar.length() - 19, inhalt_dar.length() - 18)) - 1;
stunde = s + ".-" + mehrere_stunden + ".";
mehrere_std = true;
} else {
stunde = s + ".";
}
if (inhalt_dar.length() >= 11 && inhalt_dar.substring(0, 11).equals("--rotfarbig")) {
inhalt_dar = inhalt_dar.substring(11);
rotfarbig = true;
} else {
rotfarbig = false;
}
if (inhalt_dar.length() >= 9 && inhalt_dar.substring(0, 9).equals("lehrer_fa")) {
inhalt_dar = str_replace("lehrer_fa", "", inhalt_dar);
}
if (inhalt_dar.length() >= 10 && inhalt_dar.substring(0, 10).equals("verschoben")) {
inhalt_dar = str_replace("verschoben", "", inhalt_dar);
}
if (inhalt_dar.length() >= 17 && inhalt_dar.substring(0, 17).equals("lehrer_verschoben")) {
inhalt_dar = str_replace("lehrer_verschoben", "", inhalt_dar);
}
if (inhalt_dar.length() >= 7 && inhalt_dar.substring(0, 7).equals("manuell")) {
inhalt_dar = str_replace("manuell", "", inhalt_dar);
}
if (inhalt_dar.length() >= 19 && inhalt_dar.substring(inhalt_dar.length() - 18).equals("--zellenverbindung")) {
inhalt_dar = inhalt_dar.substring(0, inhalt_dar.length() - 19);
}
if (inhalt_dar.equals("--schraffur--")) {
inhalt_dar = "X";
}
inhalt_dar = inhalt_dar.replaceAll("\\[r\\]", "");
inhalt_dar = inhalt_dar.replaceAll("\\[/r\\]", "");
inhalt_dar = inhalt_dar.replaceAll("\\[m\\]", "");
inhalt_dar = inhalt_dar.replaceAll("\\[/m\\]", "");
inhalt_dar = inhalt_dar.replaceAll("\\[\\]", "");
inhalt_dar_org.add(inhalt_dar);
inhalt_dar = inhalt_dar.replaceAll("\\n", "");
inhalt_dar = inhalt_dar.replaceAll("\\r", " ");
erg = erg + stunde + ": " + inhalt_dar + "\n";
if (mehrere_std) {
s = mehrere_stunden;
}
if (inhalt_dar.length() > 24) {
inhalt_dar = inhalt_dar.substring(0, 22) + "...";
}
stunden_val.add(stunde + ": " + inhalt_dar);
}
final String[] inhalt_dar_org_arr = inhalt_dar_org.toArray(new String[inhalt_dar_org.size()]);
[/code]

Ich sehe da keinen Zugriff auf die Oberfläche mehr oder übersehe ich da etwas?

mfg

Robert

Antworten
Felix
  • Forum-Beiträge: 259

14.02.2012, 23:09:23 via Website

Tach!

Am besten ist, wenn man solche komplexen Dinge erstmal an einem kleinen Test/Tutorial/Beispiel übt. Erst wenn das läuft und denkst, das Prinzip verstanden zu haben, solltest du das in deine eigene Anwendung einbauen, und zwar auf möglichst vergleichbare Weise. Zudem existiert Android schon ein paar Jahre und du bist nicht der erste, der auf Fehlermeldungen stößt. In der Regel findet man Hinweise zu den Gründen der Meldungen bereits im Netz.

Den Ursachen von nicht einfach zu findenden Fehlern kommt man mitunter auch, wenn man mal versucht, das Problem in einem neuen, leeren Projekt mit so wenig wie möglich darinnen nachzustellen. Man kann sich dann bei der Ursachenforschung auf das Wesentliche konzentrieren. Wenn er dann nicht auftaucht, weiß man zumindest mal, dass die Ursache in einem anderen Teil steckt.

Jedenfalls – AsyncTask vereinfacht zwar den Umgang mit Hintergrund-Aufgaben, es kann dich aber nicht vollständig von den Gegebenheiten und Bedingungen nebeneinander laufender Thread abschirmen. Deswegen ist es weiterhin wichtig zu wissen, was zum UI-Thread und was zum Hintergrund-Thread gehört und welche Kommunikationswege zwischen ihnen vorgesehen sind.


Felix.

Antworten
Robert H.
  • Forum-Beiträge: 7

15.02.2012, 11:07:50 via Website

Okay, danke!

Dann werde ich mich da nochmal genauer schlau machen.

mfg

Robert

Antworten