Istnieją powiązane pytania, takie jak Jak mogę przekazać 2 parametry do klasy AsyncTask? , ale napotkałem trudności, próbując na próżno przekazać wiele prymitywów jako parametrów do AsyncTask, więc chcę podzielić się tym, co odkryłem. Ta subtelność nie znajduje odzwierciedlenia w istniejących pytaniach i odpowiedziach, dlatego chcę pomóc każdemu, kto napotka ten sam problem, co ja, i uratować mu ból.
Pytanie jest takie: mam wiele parametrów pierwotnych (np. Dwa długie), które chcę przekazać do AsyncTask w celu wykonania w tle - jak to zrobić? (Moją odpowiedź ... po dłuższej walce z tym ... można znaleźć poniżej.)
android
android-asynctask
primitive
variadic-functions
robguinness
źródło
źródło
Odpowiedzi:
Po prostu zawiń swoje prymitywy w prosty kontener i przekaż go jako parametr do
AsyncTask
, na przykład: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; ... } }
Nazwij to tak:
MyTaskParams params = new MyTaskParams(foo, bar, arple); MyTask myTask = new MyTask(); myTask.execute(params);
źródło
Inny sposób: wystarczy dodać konstruktora MyTask do swojej klasy 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 }
Wtedy zadzwoń
new MyTask(int foo, long bar, double arple).execute();
Drugi sposób, jak odpowiedź Davida Wassera.
źródło
<(String,Object,int),Void,Void>
Nie jest (ściśle mówiąc) możliwe przekazanie wielu prymitywów do AsyncTask. Na przykład, jeśli chcesz wykonać
myTask.execute(long1, long2)
i spróbować skonfigurowaćprivate class myTask extends AsyncTask<long, Void, Void>
odpowiednią metodę:@Override protected LocationItemizedOverlay doInBackground(long... params) {...}
Twoje IDE prawdopodobnie będzie narzekać na konieczność zastąpienia metody nadrzędnego typu. Zauważ, że używasz tak zwanej sygnatury metody Varargs dla
doInBackground
, gdzie(long... params)
jest jak powiedzenie "Akceptuję zmienną liczbę długich znaków, przechowywaną jako tablica zwana params. Nie do końca rozumiem, co powoduje zgłoszenie skargi kompilatora / IDE , ale myślę, że ma to związek ze sposobemParams
zdefiniowania klasy ogólnej .W każdym razie możliwe jest osiągnięcie tego, co chcesz, bez problemu, pod warunkiem, że poprawnie rzutujesz swoje prymitywy na odpowiadające im niepierwotne opakowania (np. Int => Integer, long => Long itp.). Właściwie nie musisz jawnie rzutować swoich prymitywów na inne niż prymitywy. Wydaje się, że Java sobie z tym poradzi. Wystarczy skonfigurować ASyncTask w następujący sposób (na przykład długie pozycje):
private class MyTask extends AsyncTask<Long, Void, Void> { @Override protected void doInBackground(Long... params) { // Do stuff with params, for example: long myFirstParam = params[0] } ... }
Następnie możesz użyć tej klasy zgodnie z pierwotnymi zamierzeniami, np .:
MyTask myTask = new MyTask(); myTask.execute(long1, long2);
Lub dla dowolnej liczby prymitywów, POD warunkiem, że SĄ TEGO SAMEGO TYPU. Jeśli chcesz przekazać wiele typów prymitywów, możesz to również zrobić, ale będziesz musiał zmodyfikować powyższe, aby:
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]; } ... }
Jest to bardziej elastyczne, ale wymaga jawnego rzutowania parametrów na ich odpowiednie typy. Jeśli ta elastyczność nie jest potrzebna (np. Pojedynczy typ danych), polecam trzymać się pierwszej opcji, ponieważ jest ona nieco bardziej czytelna.
źródło
protected LocationItemizedOverlay doInBackground(Object[] objects)
i dodać następujące elementy dla definicji zadania asynchronicznego.private class MyTask extends AsyncTask<Object, Void, Void>
Wbudowana metoda execute akceptuje tablicę Params , ale wszystkie muszą być określonego typu ... więc jeśli po prostu ustawisz typ PARAM na OBJECT , możesz przekazać cokolwiek chcesz, o ile są one elementami potomnymi obiektów. ...
private class MyTask extends AsyncTask<Object, Void, Void> {
Następnie w swoim doInBackGround, po prostu rzucasz każdy parametr, aby wrócić do tego, czego potrzebujesz:
@Override protected void doInBackground(Object... params) { Context t = (Context)params[0]; String a = (String) params[1]; List<LatLng> list = (List<LatLng>)params[2]; . . .
A twoje wykonanie to po prostu:
new MyTask().execute(context,somestring,list_of_points);
Nie jest tak dobra jak umieszczenie go w swojej własnej klasie opakowującej, pakiecie, haszyszu lub czymś podobnym, ponieważ jesteś zależny od kolejności od obu stron, ale to zadziała. Oczywiście możesz po prostu uczynić swoją tablicę parametrem HashMap (,) iw zasadzie w tym momencie możesz niestandardowo implementować pakiet, ale to zadziała.
źródło
Podoba mi się metoda malajisi, ale jeśli nie, to czy nie możesz użyć klasy Bundle?
Bundle myBundle = new Bundle(); myBundle.putInt("foo", foo); myBundle.putLong("bar", bar); myBundle.putDouble("arple", arple);
Następnie po prostu podaj pakiet i rozpakuj go w MyTask. Czy to okropny pomysł? Unikasz tworzenia klasy niestandardowej i jest elastyczna, jeśli zdecydujesz, że musisz później przekazać dodatkowe parametry.
Aktualizacja: Minęło sporo lat, odkąd napisałem tę odpowiedź i teraz naprawdę mi się to nie podoba. Odradzałbym używanie pakietu. Jeśli chcesz przekazać wiele parametrów do zadania asynchronicznego (lub cokolwiek, tak naprawdę), użyj niestandardowej klasy, która przechowuje wszystkie parametry naraz. Korzystanie z pakietu to dobre rozwiązanie problemu, którego nie powinieneś mieć. Nie ma prawa zakazującego tworzenia niestandardowej klasy, która zawierałaby dokładnie to, czego potrzebujesz i nic więcej.
Poza tym, dlaczego nie używasz programów? Asynctasks to taki rok 2014.
źródło
Jest to rozwiązywane za pomocą podklas. Google ma przykład rozwiązania tego problemu (podklasy) w oficjalnej dokumentacji Android AsyncTask:
http://developer.android.com/reference/android/os/AsyncTask.html
Przykład:
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"); } }
źródło