3

ネットワーク接続を行うたびに使用するクラスを構築したいと考えています。最初にダイアログを開き、ネットワーク接続を確立して (または、SQL から何かを取得するか、Web から何かをダウンロードするか、SQL を更新して)、ダイアログを閉じます。

続行する前に、関数が終了するのを待つ必要があります。

を使用したかったのですが、どの関数を使用するAsyncTaskかを決定する方法がわかりません。AsyncTask私は 2 つの解決策を見つけました。switch-caseまたは、Java リフレクションで関数を送信しようとしました。どちらのソリューションもあまり良くありません。

誰かがこれを行うための別のアイデアや別の方法を持っていますか?

4

2 に答える 2

3

Command設計パターン の使用を検討してください。Java の例を次に示します。バックグラウンド作業が終了した後に何かを行うために、コールバックによって拡張できます。

public abstract class Command {

    protected AsyncTaskCallback callback;

    public Command(AsyncTaskCallback callback) {
            this.callback = callback;
    }

    public abstract void execute();

    public AsyncTaskCallback getCallback() {
        return callback;
    }

    public interface AsyncTaskCallback {
        public void onPreExecute();
        public void onPostExecute();
    }

}

呼び出し元:

public class Invoker extends AsyncTask<Void, Void, Void> {

    private Command command;

    public static void execute(Command command) {
            new Invoker(command).execute();
    }

    private Invoker(Command command) {
            this.command = command;
    }

    @Override
    protected Void doInBackground(Void... params) {
            return command.execute();
    }

    @Override
    protected void onPreExecute() {
            if (command.getCallback() != null) {
                    command.getCallback().onPreExecute();
            }
    }

    @Override
    protected void onPostExecute(Void result) {
            if (command.getCallback() != null) {
                    command.getCallback().onPostExecute();
            }
    }

}

したがって、AsyncTask は実行中のコマンドを認識しないため、アプリ全体で使用できます。これで、インターフェイスを実装AsyncTaskCallbackしてActivity、必要なすべての UI 関連のものを処理できます。

例:

public class MyActivity extends Activity implements AsyncTaskCallback {

...

public void onPreExecute() {
    showProgress();
}

public void onPostExecute() {
    hideProgress();
    doOtherThings();
}

...

Command myCommand = new Command(this) {
    @Override
    public void execute() {
        // Do specific background work
    }
}
Invoker.execute(command);

また、向きの変更を処理する必要があります。

于 2013-03-03T09:44:54.257 に答える
2

Android のドキュメントには、 の使用方法の良い例がありますAsyncTaskここに 1 つあります。ダイアログを表示するコードを追加したい場合は、おそらく次のようになります。

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {

     // Constant for identifying the dialog
     private static final int LOADING_DIALOG = 1000;
     private Activity parent;

     public DownloadFilesTask(Activity parent) {
         // record the calling activity, to use in showing/hiding dialogs
         this.parent = parent;
     }

     protected void onPreExecute () {
         // called on UI thread
         parent.showDialog(LOADING_DIALOG); 
     }

     protected Long doInBackground(URL... urls) {
         // called on the background thread
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         // called on the UI thread
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         // this method is called back on the UI thread, so it's safe to 
         //  make UI calls (like dismissing a dialog) here
         parent.dismissDialog(LOADING_DIALOG);
     }
 }

バックグラウンド作業を実行する前に、onPreExecute()コールバックされます。これは、サブクラスでオーバーライドするオプションのAsyncTaskメソッドですが、ネットワーク/データベースの作業が開始する前に UI をスローする機会が与えられます。

バックグラウンド作業が完了したら、 で UI を更新 (またはダイアログを削除) する別の機会がありますonPostExecute()

このクラスを ( 内からActivity) 次のように使用します。

DownloadFilesTask task = new DownloadFilesTask(this);
task.execute(new URL[] { new URL("http://host1.com/file.pdf"), 
                         new URL("http://host2.net/music.mp3") });
于 2013-03-03T08:45:14.883 に答える