programing

여러 기본 매개 변수를 AsyncTask에 어떻게 전달할 수 있습니까?

nasanasas 2020. 10. 15. 07:54
반응형

여러 기본 매개 변수를 AsyncTask에 어떻게 전달할 수 있습니까?


AsyncTask 클래스에 2 개의 매개 변수를 어떻게 전달할 수 있습니까? 와 같은 관련 질문이 있습니다 . ,하지만 AsyncTask에 매개 변수로 여러 개의 프리미티브를 전달하려는 시도가 헛되이 어려움을 겪었 기 때문에 발견 한 것을 공유하고 싶습니다. 이 미묘함은 기존의 질문과 답변에 담겨 있지 않기 때문에 저와 같은 문제에 부딪 치는 사람을 돕고 고통을 덜어주고 싶습니다.

질문은 이렇습니다. 백그라운드에서 실행되도록 AsyncTask에 전달하려는 여러 개의 기본 매개 변수 (예 : 두 개의 long)가 있습니다. 어떻게 수행 할 수 있습니까? (내 대답 ... 한동안 어려움을 겪은 후 ... 아래에서 찾을 수 있습니다.)


다음과 같이 간단한 컨테이너에 기본 요소를 래핑하고 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);

또 다른 방법 : 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();

David Wasser의 답변과 같은 두 번째 방법.


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를 설정하기 만하면됩니다 (예 : longs).

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

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

You can then use this class as you originally intended, e.g.:

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

Or for any number of primitives that you would like, PROVIDED THEY ARE OF THE SAME TYPE. If you need to pass multiple types of primitives, this can also be done, but you will need to modify the above to:

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];

    }
    ...
}

This is more flexible, but it requires explicitly casting the parameters to their respective types. If this flexibility is not needed (i.e. a single data type), I recommend sticking to the first option, as it's slightly more readable.


I like malajisi's method, but if you didn't, couldn't you use the Bundle class?

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

Then just pass the bundle and unpack it inside MyTask. Is this a terrible idea? You avoid creating a custom class, and it's flexible if you decide you need to pass additional parameters later.


The built in execute method accepts an array of Params, but they all must be of the defined type.. so if you simply set the PARAM type to OBJECT, then you can pass in whatever you like as long as they are children of objects....

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

Then in your doInBackGround, you simply cast each param in order back to what you need it to be:

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

And your execute is simply:

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

Not as good form as wrapping it in your own wrapper class, or a bundle, or hash or something, because you are order dependent on both sides, but it will work. Of course you could just make your array a param of HashMap(,) and you basically are custom implementing a bundle at that point, but it will work.


This is solved via subclassing. Google has an example for solving this problem (subclassing) in the official Android AsyncTask Documentation:

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

Example:

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");
    }
}

참고URL : https://stackoverflow.com/questions/12069669/how-can-you-pass-multiple-primitive-parameters-to-asynctask

반응형