84

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

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

4

6 に答える 6

157

プリミティブを単純なコンテナにラップし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);
于 2012-08-22T09:23:57.073 に答える
97

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

于 2014-01-14T17:38:35.423 に答える
83

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

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

IDEは、スーパータイプメソッドをオーバーライドする必要があると不平を言う可能性があります。にいわゆるVarargsメソッドシグネチャを使用していることに注意してください。これは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];

    }
    ...
}

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

于 2012-08-22T09:04:08.797 に答える
9

組み込みの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(、)のパラメーターにすることもでき、基本的にその時点でバンドルをカスタム実装していますが、それは機能します。

于 2018-01-28T03:25:10.197 に答える
7

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

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

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

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

また、なぜコルーチンを使用しないのですか?非同期タスクは2014年です

于 2014-01-30T01:48:59.400 に答える
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");
    }
}
于 2015-10-01T13:29:42.393 に答える