Hallo,
ich mal wieder.
Ich möchte gern im Hintergrund Daten herunterladen (genau genommen muss ich das tun... +knurr+).
Während des Herunterladens der Daten soll ein AlertView schön den Fortschritt des Downloads anzeigen.
(Das können 20 oder mehr MB sein, weshalb so ein Fortschrittsbalken definitiv eine gute Idee ist.)
Ich habe es aktuell so gelöst, dass ich mir eine eigene Klasse DownloadManager gebastelt habe.
Dieser bekommt eine Instanz des Interfaces DownloadManagerDelegate mit und an den kritischen Punkten sendet er seinem Delegate ein paar Informationen.
Die kritischen Punkte wären die Folgenden im Interface definierten Punkte:
public interface DownloadManagerDelegate {
public void managerDidBeginDownload(DownloadManager downloader, long expectedBytes);
public void managerDidReceiveData(DownloadManager downloader, byte[] data, long downloadedBytes, long expectedBytes);
public void managerDidFinishDownload(DownloadManager downloader, long downloadedBytes);
public void managerDidFailWithError(DownloadManager downloader, Error downloadError);
}
Nun ja, aus irgendwelchen Gründen befindet sich meine als Delegate übergebene Activity nicht im UI-Thread, so dass ich beispielsweise in der Implementierung der managerDidReceiveData(DownloadManager downloader, byte[] data, long downloadedBytes, long expectedBytes); in etwa wie folgt arbeite:
uiThread.post(new Runnable() {
@Override
public void run() {
ProgressBar fileProgressBar = (ProgressBar)downloadDialog.findViewById(R.id.progress);
TextView fileProgressPercent = (TextView)downloadDialog.findViewById(R.id.progress_percent);
TextView fileProgressNumber = (TextView)downloadDialog.findViewById(R.id.progress_number);
fileProgressBar.setProgress(downloaded);
int percent;
if(expected <= 0)
{
if(fileProgressBar.getMax() <= 0)
{
percent = -1;
}
else
{
percent = (int)(((downloaded)/(fileProgressBar.getMax()*1.0))*100);
}
}
else
{
percent = (int)((downloaded/(fileProgressBar.getMax()*1.0))*100);
}
String percentString;
if(percent == -1)
{
percentString = "%nan%";
}
else
{
percentString = percent+"%";
}
fileProgressPercent.setText(percentString);
fileProgressNumber.setText(downloaded+"/"+fileProgressBar.getMax());
}
});
Alles anzeigen
Wo ich das so einfüge sehe ich, dass ich vielleicht mit dem HolderPattern noch etwas Performance rausholen kann.
Wie dem auch sei, mir ist das alles zu langsam. Der Fortschrittbalken bleibt signifikant lange bei einem Wert, sagen wir '16%' stehen und hüpft dann quasi zu '53%'. Das sieht doof aus, zumal die Delegate-Methode alle 1024 Byte aufgerufen wird. Irgendwo hakt bei mir also die Performance.
Wie ist das unter Android übliche Vorgehen, das UI gemäß Daten aus einem anderen Thread anzupassen?
Mein von iOS bekannter Ansatz des 'Delegating' läuft hier offenbar träge bis gar nicht.
(Das 'Delegating' unter Mac OS / iOS bedient mindestens das Command Muster.)