Zápisky pro seminář programování na GJS.

Stahování z webu

Chceme stáhnout text stránky, na které je aktuální jídelní lístek.

První pokus

Nejdřív si musíme přidat žádost o připojení do AndroidManifest.xml. Má přijít jako přímý syn tagu <manifest>, takže následující řádek můžete vložit třeba jako předposlední.

<uses-permission android:name="android.permission.INTERNET" />

V layoutu aplikace si připravíme textView s tímto názvem, a libovolné tlačítko. Do kódu MainActivity si přidáme následující funkci onClick, a v layoutu pak nastavíme událost kliknutí na tlačítko.

  fun onClick(v : View) {
    val text = URL("http://www.gymjs.cz/jidelni-listek-skolni-jidelny/").readText()
    textView.setText(text)
  }

Tenhle kód ale bohužel hází NetworkOnMainThreadException. Je jasné, že tak jednoduše nám to neprojde.

Vlákno

Androidu vadí, že pracujeme se sítí na hlavním vlákně – tak mu vyhovíme, vytvoříme si vlákno nové a budeme síťovat odtamtud. Když nechceme řešit podrobnosti, nemusíme:

  fun onClick(v : View) {
    Thread {
      val text = URL("http://www.gymjs.cz/jidelni-listek-skolni-jidelny/").readText()
      textView.setText(text)
    }.start()
  }

Zjevně jsme se někam posunuli, protože Android teď hází CalledFromWrongThreadException. Výjimka zahrnuje vysvětlující zprávu, že jen hlavní vlákno smí sahat na jakékoliv View v aplikaci.

Coroutine

Budeme používat experimentální knihovnu. Proto přidáme do souboru app/build.gradle následující řádek do sekce dependencies.

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1"

Pak už můžeme použít korutinu pro volání GlobalScope z nového vlákna. Kód funkce onClick se tím zkomplikuje jen o chlup:

  fun onClick(v : View) {
    Thread {
      val text = URL("http://www.gymjs.cz/jidelni-listek-skolni-jidelny/").readText()
      GlobalScope.launch(Dispatchers.Main) {
        textView.setText(text)
      }
    }.start()
  }

Swift

V iOS by mělo jít podobnou strukturu napsat pomocí URLSession.dataTask jako vlákna a do { ... } bloku pro samotnou korutinu:

let url = URL(string: "http://www.gymjs.cz/jidelni-listek-skolni-jidelny/")!
let task = URLSession.shared.dataTask(with: URLRequest(url: url), completionHandler: { data, response, error in
  if let data = data {
    do {
      print(data)
    }
  }
})
task.resume()

Víc ukázek a podrobností se dá jako obvykle najít na Stack Overflow.