web-dev-qa-db-ja.com

複数のプリミティブパラメーターをAsyncTaskに渡すにはどうすればよいですか?

AsyncTaskクラスに2つのパラメーターを渡すにはどうすればよいですか? などの関連する質問がありますが、AsyncTaskにパラメーターとして複数のプリミティブを渡すために無駄に試みるのが困難になりました。発見したことを共有します。この微妙な点は既存の質問と回答には含まれていないので、私と同じ問題に遭遇した人を助け、痛みを軽減したいと思います。

質問はこれです:私はバックグラウンドで実行されるAsyncTaskに渡したい複数のprimitiveパラメータ(例えば2つのロング)を持っています-方法できますか? (私の答えは...しばらくこれに苦労した後...以下で見つけることができます。)

74
robguinness

次のように、プリミティブを単純なコンテナーにラップし、パラメーターとしてAsyncTaskに渡すだけです。

private static class MyTaskParams {
    int foo;
    long bar;
    double arple;

    MyTaskParams(int foo, long bar, double arple) {
        this.foo = foo;
        this.bar = bar;
        this.arple = arple;
    }
}

private class MyTask extends AsyncTask<MyTaskParams, Void, Void> {
    @Override
    protected void doInBackground(MyTaskParams... params) {
        int foo = params[0].foo;
        long bar = params[0].bar;
        double arple = params[0].arple;
        ...
    }
}

次のように呼び出します。

MyTaskParams params = new MyTaskParams(foo, bar, arple);
MyTask myTask = new MyTask();
myTask.execute(params);
147
David Wasser

別の方法:MyTaskクラスにMyTaskコンストラクターを追加するだけです:

private class MyTask extends AsyncTask<String, Void, Void> {
    int foo;
    long bar;
    double arple;

    MyTask(int foo, long bar, double arple) { 
         // list all the parameters like in normal class define
        this.foo = foo;
        this.bar = bar;
        this.arple = arple;
    }
    ......   // Here is doInBackground etc. as you did before
}

それから電話する

new MyTask(int foo, long bar, double arple).execute();

デビッドワッサーの答えのような2番目の方法。

88
malajisi

組み込みのexecuteメソッドはParamsの配列を受け入れますが、それらはすべて定義済みの型である必要があります。したがって、PARAM型をOBJECTに設定するだけの場合は、オブジェクトの子である限り、任意のものを渡すことができます。 ...

private class MyTask extends AsyncTask<Object, Void, Void> {

次に、doInBackGroundで、各パラメーターを必要なものに順番にキャストします。

 @Override
 protected void doInBackground(Object... params) {
     Context t = (Context)parms[0];
     String a = (String) params[1];
     List<LatLng> list = (List<LatLng>)params[2];
     .
     .
     .

そして、あなたの実行は単純です:

 new MyTask().execute(context,somestring,list_of_points);

独自のラッパークラス、バンドル、ハッシュ、または何かでラップするのと同じように良い形式ではありません。なぜなら、順序は両側に依存しているからです。もちろん、配列をHashMap(、)のparamにするだけで、基本的にその時点でバンドルをカスタム実装できますが、機能します。

6
Speckpgh

私はmalajisiのメソッドが好きですが、もしそうでなければ、Bundleクラスを使用できませんか?

 Bundle myBundle = new Bundle();
 myBundle.putInt("foo", foo);
 myBundle.putLong("bar", bar);
 myBundle.putDouble("arple", arple);

次に、バンドルを渡してMyTask内で展開します。これはひどい考えですか?カスタムクラスの作成を避け、後で追加のパラメーターを渡す必要があると判断した場合は柔軟です。

6
MrPlow

これはサブクラス化によって解決されます。 Googleには、公式のAndroid AsyncTaskドキュメントにこの問題を解決する例(サブクラス化)があります。

http://developer.Android.com/reference/Android/os/AsyncTask.html

例:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
        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) {
        setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        showDialog("Downloaded " + result + " bytes");
    }
}
1
Bijan