akademia androida

10
akademia androida Http i AsyncTask część VII Mobile Applications Developers www.mad.zut.edu.pl

Upload: duongcong

Post on 11-Jan-2017

234 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: akademia androida

akademia androida

Http i AsyncTaskczęść VII

Mobile Applications Developers www.mad.zut.edu.pl

Page 2: akademia androida

agenda1. URLConnection i HttpURLConnection2. UI Thread i ANR3. AsyncTask4. Zadanie

Mobile Applications Developers www.mad.zut.edu.pl

Page 3: akademia androida

1. URLConnection i HttpURLConnection

Jest to klasa, dzięki której możemy wysyłać i odbierać dane poprzez sieć. Niemusimy znać rozmiaru przesyłanych danych, co jest sporą zaletą. KlasaHttpURLConnection dziedziczy z klasy URLConnection (instancje tej klasy nie nadająsię do ponownego użycia: dla każdego połączenia musi zostać stworzony nowyobiekt).

Klasa URLConnection obsługuje 4 rodzaje protokołów:• URI (jako łącze lokalne)• FTP• HTTP i HTTPS• Jar

Używanie klasy HttpURLConnection opiera się o taki schemat:

1. Stworzenie obiektu klasy HttpURLConnection i uzyskanie połączenia dziękimetodzie openConnection(). Otrzymany wynik rzutujemy.

2. Przygotowujemy żądanie. Podstawowym parametrem żądania jest URI (wnaszym przypadku URL). Nagłówek żądania może również zawierać metadanetakie jak np. pliki cookies.

3. Odczytać odpowiedź. Nagłówek otrzymany w odpowiedzi zwykle zawierametadane takie jak typ i długość zwróconego ciała żądania, datę, czy plikicookies. Dzięki metodzie getInputStream(), która zwraca strumień zwiadomością możemy odczytać odpowiedź. W przypadku, gdy wynik naszegożądania jest pusty, metoda zwraca pusty strumień.

4. Rozłączyć się. Kiedy odczytamy ciało żądania połączenie należy zakończyć.Służy do tego metoda disconnect(). Dzięki niej zwalniamy zasobywykorzystywane przy połączeniu (można je użyć ponownie).

Przykład nawiązania połączenia ze stroną http://www.mad.zut.edu.pl/ :

URL url = new URL("http://www.mad.zut.edu.pl/"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); try { InputStream in = new BufferedInputStream(urlConnection.getInputStream()); readStream(in); finally {

urlConnection.disconnect();

}

}

Mobile Applications Developers www.mad.zut.edu.pl

Page 4: akademia androida

Metoda readStream():

private void readStream(InputStream in) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(in)); String line = ""; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }}

Ważne: nie możemy wykonywać połączenia w wątku głównym aplikacji (UIThread) w podany sposób.

Eleganckim, i zarazem praktycznym wyjściem z tej sytuacji jest użyciemechanizmu udostępnianego przez API Androida zwanego AsyncTask.

2. UI Thread i ANR

Android, jak większość dzisiejszych systemów operacyjnych wspierawielowątkowość. Nie każdy jednak zdaje sobie sprawę z tego, że aby z niejskorzystać, musimy jawnie określić jakie zadania naszej aplikacji mają byćwykonywane asynchronicznie, tj. poza głównym wątkiem aplikacji.

Należy bowiem pamiętać, że wszystkie komponenty naszej aplikacji – zarównote widoczne (Aktywności), jak i te, które teoretycznie pracują w tle (BroadcastReceivers, Usługi) uruchomione są w tym samym wątku głównym (UI Thread).

Gdy w wątku głównym wykonuje się jakaś czasochłonna czynność, użytkownikma wrażenie, że aplikacja się zawiesiła, ponieważ żaden element interfejsu niereaguje na jego akcje.

Aby zapobiec zawieszeniom, w systemie funkcjonuje mechanizm dbający opłynność działania interfejsu. Jego zadaniem jest sprawdzanie czy aplikacja nie łamie

Mobile Applications Developers www.mad.zut.edu.pl

Page 5: akademia androida

jednej z dwóch zasad:

• Czas reakcji interfejsu na zdarzenie (dotknięcie ekranu, naciśnięcie przyciskuitp.) musi być mniejszy niż 5 sekund.

• Czas wykonania zadania przez BroadcastReceiver musi być mniejszy niż 10sekund.

Kiedy któraś z powyższych zasad jest łamana, wyświetlane zostaje oknodialogowe ANR (Application Not Responding). Daje ono użytkownikowi możliwośćzatrzymania naszej aplikacji, co skutkuje jej awaryjnym wyłączeniem.

3. AsyncTask

Abstrakcyjna klasa AsyncTask jest prostym mechanizmem, który pozwala naprzeniesienie czasochłonnych zadań do nowego wątku. Oprócz tego umożliwia onawykonywanie zadań w głównym wątku aplikacji (UI Thread), dzięki czemu w łatwysposób możemy sterować interfejsem użytkownika.

Przykład deklaracji klasy wykorzystującej AsyncTask:

private class LongTask extends AsyncTask<Integer, Integer, Long> {//class code

}

Klasy rozszerzające AsyncTask są deklarowane jako prywatne i wykorzystywanewewnątrz danej aktywności.

Parametry klasy (typy generyczne, nie można używać typów prymitywnych, jaknp. : int, boolean, itd.) AsyncTask<Params, Progress, Result> :

• Params – typ danych wejściowych• Progress – typ danych przedstawiających postęp w działaniu• Result – typ zwracany przez zadanie

Gdy któregoś nie potrzebujemy wstawiamy Void.

Metody, które możemy przeciążyć dziedzicząc po AsyncTask to:

• onPreExecute() – wywoływana zaraz przed uruchomieniem właściwegozadania. Metoda ta wykonywana jest w wątku głównym aplikacji, dzięki czemu

Mobile Applications Developers www.mad.zut.edu.pl

Page 6: akademia androida

możemy w niej skonfigurować interfejs aplikacji (np. wyświetlić ProgressBaralbo zablokować przyciski).

• doInBackground(Params… params) – jedyna metoda, która uruchamiana jestw oddzielnym wątku. To tutaj powinniśmy umieścić wszystkie czasochłonneczynności. Nie ma dostępu do wątku głównego aplikacji, w związku z czymjedynym sposobem na zaktualizowanie stanu interfejsu jest wywołaniemetody publishProgress(Progress… values).

• onProgressUpdate(Progress… values) – metoda wywoływana jest wmomencie wywołania publishProgress(…) wspomnianego powyżej. Równieżwykonywana jest w głównym wątku aplikacji, w związku z czym służy ona doaktualizacji informacji o postępie wykonywanej czynności.

• onPostExecute(Result result) – wywoływana w momencie zakończeniapracy doInBackground(…). Argumentem metody jest wynik zwróconyprzez doInBackground(…). Również i tutaj mamy dostęp do komponentówinterfejsu, w związku z czym z tego miejsca konfigurujemy wszystkie widoki powykonaniu pracy.

• onCancelled() - w związku z tym, że możemy w każdej chwili anulowaćwykonywanie zadania (metoda cancel(…)), możemy zaimplementowaćobsługę takiego stanu. W takim wypadku jednakmetoda doInBackground(…) będzie nadal wykonywana do końca. Natomiastpo jej zakończeniu zamiast wykonać onPostExecute(…) wykonana będziemetoda onCancelled().

Typy argumentów z metod doInBackground(…), onProgressUpdate(…) orazonPostExecute(…) są parametrami klasy AsyncTask.

By uruchomić zadanie, wystarczy wywołać metodę execute(). Przykład dlaklasy LongTask:

private void launchMyTask(){new LongTask().execute();

}

Mobile Applications Developers www.mad.zut.edu.pl

Page 7: akademia androida

Prosta aplikacja odświeżająca ProgressBar:

package pl.edu.zut.wi.mad; import android.app.Activity;import android.os.AsyncTask;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.ProgressBar; public class MainActivity extends Activity { final private int START_PROGRESS = 0; final private int STOP_PROGRESS = 100; private Button button; private ProgressBar progressBar; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); progressBar = (ProgressBar)findViewById(R.id.progressbar_Horizontal); button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new WymagajacyWatek().execute(""); }}); } private class WymagajacyWatek extends AsyncTask<String, Integer, String>{ @Override protected String doInBackground(String... arg0) { int i,a; for(i = 0; i < 100; i++){ publishProgress(i); a = 0; while(a<1500){ a++; } }

Mobile Applications Developers www.mad.zut.edu.pl

Page 8: akademia androida

return null; } @Override protected void onPostExecute(String result) { setProgressBar(STOP_PROGRESS); button.setEnabled(true); } @Override protected void onPreExecute() { //"wyzerujemy" progress bar setProgressBar(START_PROGRESS); //zablokujmy przycisk na czas dzialania watku button.setEnabled(false); } @Override protected void onProgressUpdate(Integer... progress) { setProgressBar(progress[0]); } } private void setProgressBar(int progress){ progressBar.setProgress(progress); }}

4. Zadanie

• Stworzyć layout składający się z 3 elementów: Buttona, ProgressBara(poziomego) i ImageView

• Po wciśnięciu Buttona ma odpalać się zdarzenie obsługiwane przez AsyncTask◦ Na czas działania zdarzenia AsyncTask wyłączamy obsługę Buttona

• W klasie dziedziczącej z AsyncTask musimy obsłużyć:◦ połączenie ze stroną◦ pobranie obrazka i zapisanie go na kartę pamięci urządzenia◦ odświeżanie stanu ProgressBara (uzależnić postęp na pasku od rozmiaru

pliku)◦ wyświetlenie pobranego obrazka z pamięci telefonu w ImageView

Mobile Applications Developers www.mad.zut.edu.pl

Page 9: akademia androida

Mobile Applications Developers www.mad.zut.edu.pl

Page 10: akademia androida

Dziękuję za uwagę

kontakt:

[email protected][email protected]

Mobile Applications Developers www.mad.zut.edu.pl