Mam te dwie klasy. Mój główny aktywny i jeden, który rozszerza AsyncTask
Teraz moim głównym Aktywny Muszę dostać wynik od OnPostExecute()
w AsyncTask
. Jak mogę przekazać lub uzyskać wynik mojej głównej działalności?
Oto przykładowe kody.
Moja główna aktywność.
public class MainActivity extends Activity{
AasyncTask asyncTask = new AasyncTask();
@Override
public void onCreate(Bundle aBundle) {
super.onCreate(aBundle);
//Calling the AsyncTask class to start to execute.
asyncTask.execute(a.targetServer);
//Creating a TextView.
TextView displayUI = asyncTask.dataDisplay;
displayUI = new TextView(this);
this.setContentView(tTextView);
}
}
To jest klasa AsyncTask
public class AasyncTask extends AsyncTask<String, Void, String> {
TextView dataDisplay; //store the data
String soapAction = "http://sample.com"; //SOAPAction header line.
String targetServer = "https://sampletargeturl.com"; //Target Server.
//SOAP Request.
String soapRequest = "<sample XML request>";
@Override
protected String doInBackground(String... string) {
String responseStorage = null; //storage of the response
try {
//Uses URL and HttpURLConnection for server connection.
URL targetURL = new URL(targetServer);
HttpURLConnection httpCon = (HttpURLConnection) targetURL.openConnection();
httpCon.setDoOutput(true);
httpCon.setDoInput(true);
httpCon.setUseCaches(false);
httpCon.setChunkedStreamingMode(0);
//properties of SOAPAction header
httpCon.addRequestProperty("SOAPAction", soapAction);
httpCon.addRequestProperty("Content-Type", "text/xml; charset=utf-8");
httpCon.addRequestProperty("Content-Length", "" + soapRequest.length());
httpCon.setRequestMethod(HttpPost.METHOD_NAME);
//sending request to the server.
OutputStream outputStream = httpCon.getOutputStream();
Writer writer = new OutputStreamWriter(outputStream);
writer.write(soapRequest);
writer.flush();
writer.close();
//getting the response from the server
InputStream inputStream = httpCon.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);
int intResponse = httpCon.getResponseCode();
while ((intResponse = bufferedReader.read()) != -1) {
byteArrayBuffer.append(intResponse);
}
responseStorage = new String(byteArrayBuffer.toByteArray());
} catch (Exception aException) {
responseStorage = aException.getMessage();
}
return responseStorage;
}
protected void onPostExecute(String result) {
aTextView.setText(result);
}
}
android
android-asynctask
Stella
źródło
źródło
Odpowiedzi:
Łatwy:
Utwórz
interface
klasę, gdzieString output
jest opcjonalna lub może być dowolną zmienną, którą chcesz zwrócić.Idź do swojej
AsyncTask
klasy i zadeklaruj interfejsAsyncResponse
jako pole:W swojej głównej działalności musisz się
implements
połączyćAsyncResponse
.AKTUALIZACJA
Nie wiedziałem, że jest to ulubieniec wielu z was. Oto prosty i wygodny sposób użycia
interface
.nadal używam tego samego
interface
. Do twojej wiadomości, możesz połączyć to wAsyncTask
klasę.w
AsyncTask
klasie:zrób to w swojej
Activity
klasieLub ponownie implementując interfejs działania
Jak widać 2 rozwiązania powyżej, pierwsze i trzecie, musi utworzyć metodę
processFinish
, drugie, metoda znajduje się w parametrze dzwoniącego. Trzeci jest bardziej schludny, ponieważ nie ma zagnieżdżonej anonimowej klasy. Mam nadzieję że to pomożeWskazówka : Zmiana
String output
,String response
iString result
do różnych typów dopasowania w celu uzyskania różnych obiektów.źródło
Istnieje kilka opcji:
Zagnieżdż
AsyncTask
klasę w swojejActivity
klasie. Zakładając, że nie używasz tego samego zadania do wielu działań, jest to najłatwiejszy sposób. Cały kod pozostaje taki sam, wystarczy przenieść istniejącą klasę zadania, aby była klasą zagnieżdżoną w klasie działania.Utwórz własny konstruktor,
AsyncTask
który odwołuje się do TwojegoActivity
. Utworzyłbyś zadanie z czymś takimnew MyAsyncTask(this).execute(param1, param2)
.źródło
static
? Po prostu użyj dowolnegofieldOrMethod
zMyActivity
lubMyActivity.this.fieldOrMethod
jeśli jest w cieniu.MyAsyncTask
się nie wewnętrzną klasy.private
/protected
dla klas najwyższego poziomu jest niedozwolony, dlatego pomyślałem, że to musi byćstatic
klasa inna niż wewnętrzna.Czułem, że poniższe podejście jest bardzo łatwe.
Zadeklarowałem interfejs do oddzwaniania
Następnie utworzono asynchroniczne zadanie odpowiadające na wszystkie typy równoległych żądań
Następnie wywołano zadanie asynchroniczne po kliknięciu przycisku w klasie aktywności.
Dzięki
źródło
Możesz wypróbować ten kod w swojej klasie głównej. To działało dla mnie, ale zaimplementowałem metody w inny sposób
źródło
execute()
, zobacz moją odpowiedź, dodałem tam komentarz. możesz sprawdzić moją zaktualizowaną odpowiedź. mam nadzieję że to pomoże.Ta odpowiedź może się spóźnić, ale chciałbym wspomnieć o kilku rzeczach, kiedy jesteś
Activity
na utrzymaniuAsyncTask
. Pomoże to w zapobieganiu awariom i zarządzaniu pamięcią. Jak już wspomniano w powyższych odpowiedziach iść zinterface
, możemy również powiedzieć im wywołania zwrotne. Będą działać jako informator, ale nigdy nie wysyłają silnych referencjiActivity
lubinterface
zawsze używają słabych referencji w takich przypadkach.Sprawdź poniższy zrzut ekranu, aby dowiedzieć się, w jaki sposób może to powodować problemy.
Jak widać, jeśli zaczęliśmy
AsyncTask
od silnego odniesienia, nie ma gwarancji, że naszeActivity
/Fragment
będą żyły, dopóki nie otrzymamy danych, więc lepiej byłoby użyćWeakReference
w takich przypadkach, a to również pomoże w zarządzaniu pamięcią, ponieważ nigdy nie będziemy posiadać zdecydowana referencja naszegoActivity
wówczas będzie kwalifikować się do zbierania śmieci po ich zniekształceniu.Sprawdź poniższy fragment kodu, aby dowiedzieć się, jak używać niesamowitego WeakReference -
MyTaskInformer.java
Interfejs, który będzie działał jako informator.MySmallAsyncTask.java
AsyncTask wykonuje długo działające zadanie, które wykorzystaWeakReference
.MainActivity.java
Ta klasa służy do uruchomienia mojegoAsyncTask
implementacjiinterface
na tej klasie i naoverride
tej obowiązkowej metodzie.źródło
w swoim Oncreate ():
`
} `
źródło
Możesz to zrobić w kilku wierszach, po prostu zastąp parametr onPostExecute podczas wywoływania funkcji AsyncTask. Oto przykład dla ciebie:
Mam nadzieję, że ci pomogło, wesołego kodowania :)
źródło
onPostExecute
metodę.Dlaczego ludzie utrudniają to.
To powinno wystarczyć.
Nie implementuj metody onPostExecute w zadaniu asynchronicznym, a raczej implementuj ją w działaniu:
źródło
@Override
?Możesz wywołać
get()
metodęAsyncTask
(lub przeciążonąget(long, TimeUnit)
). Ta metoda będzie blokować doAsyncTask
czasu zakończenia pracy, w którym to momencie zwróci CiResult
.Rozsądnie byłoby wykonać inną pracę między utworzeniem / uruchomieniem zadania asynchronicznego a wywołaniem
get
metody, w przeciwnym razie zadanie asynchroniczne nie będzie wykorzystywane bardzo skutecznie.źródło
Możesz napisać własnego słuchacza. Jest taki sam jak odpowiedź HelmiB , ale wygląda bardziej naturalnie:
Utwórz interfejs odbiornika:
Następnie napisz swoje zadanie asynchroniczne:
Na koniec zaimplementuj nasłuchiwanie w działaniu:
I tak możesz wywołać asyncTask:
źródło
Cześć, możesz zrobić coś takiego:
Utwórz klasę, która implementuje AsyncTask
Dodaj główną aktywność
źródło
Utwórz statycznego członka w swojej klasie aktywności. Następnie przypisz wartość podczas
onPostExecute
Na przykład, jeśli wynikiem AsyncTask jest ciąg znaków, utwórz publiczny ciąg statyczny w swoim działaniu
public static String dataFromAsyncTask;
Następnie w
onPostExecute
AsyncTask po prostu wywołaj statyczne wywołanie swojej klasy głównej i ustaw wartość.MainActivity.dataFromAsyncTask = "result blah";
źródło
Sprawiam, że działa za pomocą wątków i handlera / wiadomości. Kroki, jak następuje: Zadeklaruj okno dialogowe postępu
Utwórz funkcję, aby zamknąć okno dialogowe po zakończeniu operacji.
Zakoduj dane swojego wykonania:
źródło
Musisz użyć „protokołów”, aby przekazać lub przekazać dane do
AsynTask
.Delegaci i źródła danych
Delegat to obiekt, który działa w imieniu lub w koordynacji z innym obiektem, gdy ten obiekt napotka zdarzenie w programie. ( Definicja Apple )
protokoły to interfejsy, które definiują niektóre metody delegowania niektórych zachowań.
Oto kompletny przykład !!!
źródło
Spróbuj tego:
I przykład użycia:
źródło
Prawdopodobnie trochę przesadzam, ale zapewniłem wywołania zwrotne zarówno dla kodu wykonania, jak i wyników. oczywiście dla bezpieczeństwa wątków chcesz uważać na to, do czego masz dostęp w wywołaniu zwrotnym wykonania.
Implementacja AsyncTask:
Oddzwonienie:
I wreszcie wykonanie zadania asynchronicznego:
źródło
Mam nadzieję, że przez to przeszliście , jeśli nie, proszę przeczytać.
https://developer.android.com/reference/android/os/AsyncTask
W zależności od charakteru danych wynikowych należy wybrać najlepszą możliwą opcję, o której można pomyśleć.
To świetny wybór do używania interfejsu
niektóre inne opcje to ...
Jeśli klasa AsyncTask jest zdefiniowana w tej samej klasie, w której chcesz użyć wyniku Użyj statycznej zmiennej globalnej lub get () , użyj jej z klasy zewnętrznej (w razie potrzeby zmienna lotna ). ale powinien być świadomy postępu AsyncTask lub powinien przynajmniej upewnić się, że zadanie zostało zakończone, a wynik jest dostępny za pośrednictwem metody zmiennej globalnej / get (). możesz użyć odpytywania, onProgressUpdate (Progress ...) , synchronizacji lub interfejsów (które kiedykolwiek najlepiej Ci odpowiadają)
Jeśli wynik jest zgodny z wpisem sharedPreference lub zapisanie go jako pliku w pamięci jest w porządku, możesz zapisać go nawet z samego zadania w tle i użyć metody onPostExecute () ,
aby otrzymywać powiadomienia, gdy wynik jest dostępny w pamięć.
Jeśli łańcuch jest wystarczająco mały i ma być używany przy rozpoczęciu działania. możliwe jest użycie intencji ( putExtra () ) w ramach onPostExecute () , ale pamiętaj, że konteksty statyczne nie są tak bezpieczne, aby sobie z nimi poradzić.
Jeśli to możliwe, można wywołać metodę statyczną z metody onPostExecute (), przy czym wynikiem jest parametr
źródło