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]
}
...
}
그런 다음 원래 의도 한대로이 클래스를 사용할 수 있습니다. 예 :
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];
}
...
}
이것은 더 유연하지만 매개 변수를 각각의 유형으로 명시 적으로 캐스팅해야합니다. 이러한 유연성이 필요하지 않은 경우 (즉, 단일 데이터 유형), 약간 더 읽기 쉬운 첫 번째 옵션을 고수하는 것이 좋습니다.
답변
내장 된 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 (,)의 매개 변수로 만들 수 있으며 기본적으로 그 시점에서 번들을 사용자 정의 구현하지만 작동합니다.
답변
나는 malajisi의 방법을 좋아하지만 그렇지 않다면 Bundle 클래스를 사용할 수 없습니까?
Bundle myBundle = new Bundle();
myBundle.putInt("foo", foo);
myBundle.putLong("bar", bar);
myBundle.putDouble("arple", arple);
그런 다음 번들을 전달하고 MyTask에서 압축을 풉니 다. 이것은 끔찍한 생각입니까? 사용자 지정 클래스를 만들지 않고 나중에 추가 매개 변수를 전달해야하는 경우 유연합니다.
업데이트 :이 답변을 작성한 지 꽤 몇 년이 지났고 지금은 정말 싫어합니다. 번들을 사용하지 않는 것이 좋습니다. 여러 매개 변수를 비동기 작업 (또는 실제로)에 전달해야하는 경우 모든 매개 변수를 한 번에 보유하는 사용자 정의 클래스를 사용하십시오. 번들을 사용하면 안되는 문제에 대한 훌륭한 해결책이됩니다. 필요한 것을 정확히 담기 위해 커스텀 클래스를 만드는 법은 없습니다.
또한 코 루틴을 사용하지 않는 이유는 무엇입니까? Asynctasks은 그래서 2014.
답변
이것은 서브 클래 싱을 통해 해결됩니다. 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");
}
}