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


82

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

질문은 이것이다 : 백그라운드에서 실행될 AsyncTask에 전달하려는 여러 개의 기본 매개 변수 (예 : 두 개의 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

10
이것은 실제로 나를 훨씬 더 멋지게 친다. 나는 그것을 사용하는 Object ... params 방식을 사용하고 있으며 어떤 이유로 든 기분이 좋지 않거나 안전하지 않습니다.
Mafro34 2011

1
참 친구처럼 일해 .. 나눔 주셔서 감사합니다 ..!
Deepak S. Gavkar

2
매우 우아합니다.
Sipty

1
@DavidWasser : 주어진 솔루션 외에도 업데이트에 감사드립니다!
Moussa

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();

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


9
실제로 이것은 다른 유형의 인수를 전달하는 세 가지 방법 중 내가 가장 좋아하는 방법입니다. 캐스팅 할 개체가없고 추가 클래스를 만들 필요가 없습니다.
QuickFix 2014 년

3
재정의 된 생성자에서 super ()를 호출해야합니다!
zyamys 2015

2
@zyamys 왜 여기에 super ()가 필요합니까? 내가 이해했듯이 자동으로 호출됩니다. 여기 참조 stackoverflow.com/a/2054040/984263
carthurs

이 스레드의 옵션 중에서 나는 이것을 가장 좋아합니다. 도우미 클래스가 없습니다.이 클래스는 자체적으로 사용할 수 있으며 자체 요구 사항을 설명합니다. 전달되는 미스터리 개체가 없습니다. 감사.
Vinnyq12

작동합니다. 매우 더럽지 만 다른 것을 시도하기에는 너무 게으르다. 이것을 기본적으로 수행하는 좋은 기본 방법이 없다는 것을 믿을 수 없습니다. 나중에 자바에서 지원 가능<(String,Object,int),Void,Void>
Sirens

82

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]
    }
    ...
}

그런 다음 원래 의도 한대로이 클래스를 사용할 수 있습니다. 예 :

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

8

내장 된 execute 메소드는 Params 배열을 받아들이지 만 모두 정의 된 유형이어야합니다. 따라서 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
여기 사람들은 멋진 기술로 너무 멋지다. 그리고 이것이 내가 가장 좋아하는 것이었다!
George Udosen 2008

7

나는 malajisi의 방법을 좋아하지만 그렇지 않다면 Bundle 클래스를 사용할 수 없습니까?

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

그런 다음 번들을 전달하고 MyTask에서 압축을 풉니 다. 이것은 끔찍한 생각입니까? 사용자 지정 클래스를 만들지 않고 나중에 추가 매개 변수를 전달해야하는 경우 유연합니다.

업데이트 :이 답변을 작성한 지 꽤 몇 년이 지났고 지금은 정말 싫어합니다. 번들을 사용하지 않는 것이 좋습니다. 여러 매개 변수를 비동기 작업 (또는 실제로)에 전달해야하는 경우 모든 매개 변수를 한 번에 보유하는 사용자 정의 클래스를 사용하십시오. 번들을 사용하면 안되는 문제에 대한 훌륭한 해결책이됩니다. 필요한 것을 정확히 담기 위해 커스텀 클래스를 만드는 법은 없습니다.

또한 코 루틴을 사용하지 않는 이유는 무엇입니까? Asynctasks은 그래서 2014.


그게 좋은 생각
BQuadra

좋은 생각입니다. 나는 이것이 정의 지원 doInBackground ()에 전달되는 객체하지 않습니다 그러나 가정
존 워드

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.