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


82

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

質問はこれです:バックグラウンドで実行するためにAsyncTaskに渡したい複数のプリミティブパラメータ(たとえば2つのlong)があります-どのようにそれを行うことができますか?(私の答えは...しばらくこれに苦労した後...以下にあります。)


回答:


153

プリミティブを単純なコンテナにラップし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);

これも機能します。しかし、上記のオプションの方が簡単だと思います。
robguinness 2012

10
これは実際にはもっといいと思います。私はそれを行うためにObject ... paramsの方法を使用してきましたが、何らかの理由でそれを行うのは気分が悪いか安全ではありません。
mafro34 2013年

1
チャームバディのように働く..共有してくれてありがとう..!
Deepak S. Gavkar 2016年

2
とてもエレガントで、大好きです。
Sipty 2016年

1
@DavidWasser:与えられた解決策がうまく機能することに加えて、あなたの更新に感謝します!
ムッサ2018

93

別の方法: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番目の方法。


9
実際、これは、異なるタイプの引数を渡す3つの方法の中で私のお気に入りの方法です。キャストするオブジェクトはなく、追加のクラスを作成する必要もありません。
QuickFix 2014年

3
オーバーライドされたコンストラクターでsuper()を呼び出す必要があります!
zyamys 2015

2
@zyamysなぜここでsuper()が必要なのですか?私が理解しているように、それは自動的に呼び出されます。ここを参照してくださいstackoverflow.com/a/2054040/984263
carthurs

このスレッドのオプションの中で、私はこれが一番好きです。ヘルパークラスはありません。このクラスは単独で使用でき、独自の要件を記述します。ミステリーオブジェクトは渡されません。ありがとう。
Vinnyq12 2016年

これは機能します。とても汚い感じがしますが、私は怠惰すぎて他のことを試すことができません。これをネイティブに行うための優れたネイティブの方法がないことを信じることができません。後でJavaでサポートされる可能性があります<(String,Object,int),Void,Void>
Sirens 2017

82

(厳密に言えば)複数のプリミティブをAsyncTaskに渡すことはできません。たとえば、対応する方法で実行myTask.execute(long1, long2)してセットアップを試みたい場合は、次のようにしますprivate class myTask extends AsyncTask<long, Void, Void>

@Override
protected LocationItemizedOverlay doInBackground(long... params) {...}

IDEは、スーパータイプメソッドをオーバーライドする必要があると文句を言う可能性があります。あなたは、いわゆる使用していることを注意可変引数のメソッドのシグネチャをdoInBackground(long... params)私は配列と呼ばれるのparamsとして格納され、long型の変数の数を受け入れる」というようなものです。私は完全にコンパイラ/ IDEの苦情の原因を理解していないが発生します、しかし、それはジェネリッククラスParamsがどのように定義されているかに関係していると思います。

いずれの場合も、プリミティブをそれぞれの非プリミティブラッパー(たとえば、int => Integer、long => Longなど)に正しくキャストすれば、問題なく目的を達成できます。実際には、プリミティブを非プリミティブに明示的にキャストする必要はありません。Javaはあなたのためにそれを処理するようです。次のようにASyncTaskを設定する必要があります(longの例の場合)。

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

    @Override
    protected void doInBackground(Long... params) {
        // Do stuff with params, for example:
        long myFirstParam = params[0]
    }
    ...
}

その後、最初に意図したとおりにこのクラスを使用できます。例:

MyTask myTask = new MyTask();
myTask.execute(long1, long2);

または、必要なプリミティブの数に応じて、それらが同じタイプであることが提供されます。複数のタイプのプリミティブを渡す必要がある場合は、これも実行できますが、上記を次のように変更する必要があります。

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

    @Override
    protected void doInBackground(Object... params) {
        // Do stuff with params, for example:
        long myLongParam = (Long) params[0];
        int myIntParam = (Integer) params[1];

    }
    ...
}

これはより柔軟性がありますが、パラメーターをそれぞれのタイプに明示的にキャストする必要があります。この柔軟性が必要ない場合(つまり、単一のデータ型)、少し読みやすいので、最初のオプションを使用することをお勧めします。


メソッドに以下を使用protected LocationItemizedOverlay doInBackground(Object[] objects) し、非同期タスク定義に以下を追加することもでき ます。 private class MyTask extends AsyncTask<Object, Void, Void>
Hany Sakr 2017年

8

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

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

次に、doInBackGroundで、必要なものに戻すために各パラメータをキャストするだけです。

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

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

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

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


1
ここの人々はとてもクールで、たくさんのクールなテクニックがあり、これが私のお気に入りでした!
ジョージウドセン2018年

7

私はmalajisiのメソッドが好きですが、そうでない場合は、Bundleクラスを使用できませんでしたか?

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

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

更新:この回答を書いてからかなりの年月が経ちましたが、今は本当に嫌いです。バンドルの使用はお勧めしません。複数のパラメーターを非同期タスク(または実際には何か)に渡す必要がある場合は、すべてのパラメーターを一度に保持するカスタムクラスを使用してください。バンドルを使用することは、あなたが持つべきではない問題に対する素晴らしい解決策です。必要なものを正確に保持するカスタムクラスを作成することを禁じる法律はありません。

また、なぜコルーチンを使用しないのですか?Asynctasksがあるので、 2014。


それはいいことだと思います
BQuadra 2015年

いい案。ただし、これはカスタムオブジェクトがdoInBackground()に渡されることをサポートしていないと思います
John Ward

1

これはサブクラス化によって解決されます。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");
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.