Beste Weg, um zu verwalten, der ProgressDialog von AsyncTask
Ich würde gerne die AsyncTask
für die Verwaltung einige business-Logik in meiner Anwendung. Was ist das beste Muster für die Verwendung der onProgressUpdate(...)
Methode der AsyncTask
definiert in separed-Dateien (nicht als innter Klasse Activity
)
Ich habe zwei Ideen:
1. Der einfachste Weg: erstellen ProgressDialog
im Activity
(mit onCreateDialog(...)
- Methode) und pass Verweis auf meine Unterklasse von AsyncTask
durch den Konstruktor überschreiben onProgressUpdate(...)
in meinem AsyncTask
Unterklasse). Der Nachteil dieser Lösung ist die Verwendung von UI-Komponenten innerhalb von business-Logik-code.
FooTask1.java:
public class FooTask1 extends AsyncTask<Void, Integer, Void> {
private ProgressDialog mProgressDialog;
public FooTask1(ProgressDialog progressDialog) {
super();
mProgressDialog = progressDialog;
}
@Override
protected Void doInBackground(Void... unused) {
//time consuming operation
for (int i=0; i<=100; i++) {
this.publishProgress(i);
try {
Thread.sleep(100);
} catch (Exception e) {}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
mProgressDialog.setProgress(progress[0]);
}
@Override
protected void onPostExecute(Void result) {
mProgressDialog.dismiss();
}
}
FooActivity1.java:
public class FooActivity1 extends Activity {
private static final int DIALOG_PROGRESS_ID = 0;
private ProgressDialog mProgressDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showDialog(DIALOG_PROGRESS_ID);
new FooTask(mProgressDialog).execute();
}
@Override
protected Dialog onCreateDialog(int id) {
switch(id) {
case DIALOG_PROGRESS_ID:
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setMessage("Loading...");
mProgressDialog.setCancelable(false);
return mProgressDialog;
default:
return null;
}
}
}
2.Der anspruchsvollere Weg: überschreiben Sie die onProgressUpdate(...)
Methode der AsyncTask
innerhalb der Activity
Klasse:
FooTask2.java:
public class FooTask2 extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... unused) {
//time consuming operation
for (int i=0; i<=100; i++) {
this.publishProgress(i);
try {
Thread.sleep(100);
} catch (Exception e) {}
}
return null;
}
}
FooActivity2.java
public class FooActivity2 extends Activity {
private static final int DIALOG_PROGRESS_ID = 0;
private ProgressDialog mProgressDialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showDialog(DIALOG_PROGRESS_ID);
new FooTaskLoader().execute();
}
@Override
protected Dialog onCreateDialog(int id) {
switch(id) {
case DIALOG_PROGRESS_ID:
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setMessage("Loading...");
mProgressDialog.setCancelable(false);
return mProgressDialog;
default:
return null;
}
}
private class FooTaskLoader extends FooTask2 {
@Override
protected void onProgressUpdate(Integer... progress) {
mProgressDialog.setProgress(progress[0]);
}
@Override
protected void onPostExecute(Void result) {
dismissDialog(DIALOG_PROGRESS_ID);
}
}
}
- Kannst du noch ein wenig mehr, warum Sie nicht möchten, dass AsyncTask implementieren als innere Klasse?
- Zur Verbesserung der Testbarkeit und Wiederverwendbarkeit von FooTask Klasse durch die Trennung der Benutzeroberfläche von der Logik Zeug.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde eher isolieren, business-Logik-Sachen von AsyncTask als isolieren AsyncTask von Aktivität.
Im Allgemeinen, AsyncTask hat eine sehr spezifische design-und case-Android application-life-cycle, das heißt, führen Sie einige Zeit raubende Aufgabe in den hintergrund-thread, wenn Sie fertig sind, aktualisieren-Aktivität anzeigen in der UI-thread. Deshalb ist es immer empfohlen, es als innere Klasse der Activity.
Mehr OO-design IMO ist die Isolierung und Zentralisierung Ihrer business-Logik in ein POJO (Wiederverwendbarkeit). Für Testbarkeit, können Sie etwas wie das hier tun:
1. Definieren Sie eine Schnittstelle IBusinessDAO
2. Definieren RealBusinessDAO implementiert IBusinessDAO
3. Definieren MockBusinessDAO implementiert IBusinessDAO
4. Rufen Sie IBusinessDAO.foo(); in AsyncTask.doInBackground()
Unit-testen Sie Ihre business-Logik, wie es ist ein POJO, die Sie verwenden können, rein JUnit schreiben Sie Ihre test-Fall. Manchmal wollen wir zu test-UI-Komponente und die wir nicht wirklich, wie die zugrunde liegenden business-Logik implementiert ist, zum Beispiel, meine business-Logik verbinden zu remote-http-server download einige json-Daten, ich will nicht, dies zu tun jedes mal, wenn ich nur testen will, das UI-layout, für diese situation, das kann ich leicht ändern, meine Tätigkeit verwenden MockBusinessDAO (Art Frühling DI-Konzept) wie folgt:
Einige Vorteile zu tun, diese sind:
1. AsyncTask Implementierung ist einfach und sauber (mehrere Codezeilen in doInBacnground())
2. Business-logic-Implementierung ist rein POJO, Verbesserung der Wiederverwendbarkeit.
3. Isolation test von business-Logik und UI-Komponenten, Verbesserung der Testbarkeit.
Hoffe, dass hilft.
Lösung Nummer eins ist wohl, wie ich es handhaben würde - Das ist der Weg des Android-framework. Eine Drehung um diese Lösung (und wahrscheinlich, wie ich es handhaben würde, wenn die
AsyncTask
konnte nicht passen in dieActivity
-Klasse) würde ich passieren eineContext
als parameter statt, und dann instanziieren und zeigen Sie dasProgressDialog
imonPreExecute
.Lösung Nummer 2 ist im Grunde das gleiche wie das erstellen der dialog als innere Klasse - so könnten Sie aswell tun, wenn Sie gehen für diese ein.