執(zhí)行一個請求
對于感受我們要實現(xiàn)的想法而言,我們目前的文本是很好開始,但是現(xiàn)在是時候去請求一些顯示在RecyclerView上的真正的數(shù)據(jù)了。我們將會使用OpenWeatherMap API來獲取數(shù)據(jù),還有一些普通類來現(xiàn)實這個請求。多虧Kotlin非常強大的互操作性,你可以使用任何你想使用的庫,比如用Retrofit來執(zhí)行服務(wù)器請求。當(dāng)只是執(zhí)行一個簡單的API請求,我們可以不使用任何第三方庫來簡單地實現(xiàn)。
而且,如你所見,Kotlin提供了一些擴展函數(shù)來讓請求變得更簡單。首先,我們要創(chuàng)建一個新的Request類:
public class Request(val url: String) {
public fun run() {
val forecastJsonStr = URL(url).readText()
Log.d(javaClass.simpleName, forecastJsonStr)
}
}
我們的請求很簡單地接收一個url,然后讀取結(jié)果并在logcat上打印json。實現(xiàn)非常簡單,因為我們使用readText,這是Kotlin標準庫中的擴展函數(shù)。這個方法不推薦結(jié)果很大的響應(yīng),但是在我們這個例子中已經(jīng)足夠好了。
如果你用這些代碼去比較Java,你會發(fā)現(xiàn)我們僅使用標準庫就節(jié)省了大量的代碼。比如HttpURLConnection、BufferedReader和需要達到相同效果所必要的迭代結(jié)果,管理連接狀態(tài)、reader等部分的代碼。很明顯,這些就是場景背后函數(shù)所作的事情,但是我們卻不用關(guān)心。
為了可以執(zhí)行請求,App必須要有Internet權(quán)限。所以需要在AndroidManifest.xml中添加::
<uses-permission android:name="android.permission.INTERNET" />
在主線程以外執(zhí)行請求
如你所知,HTTP請求不被允許在主線程中執(zhí)行,否則它會拋出異常。這是因為阻塞住UI線程是一個非常差的體驗。Android中通用的做法是使用AsyncTask,但是這些類是非常丑陋的,并且使用它們無任何副作用地實現(xiàn)功能也是非常困難的。如果你使用不小心,AsyncTasks會非常危險,因為當(dāng)運行到postExecute時,如果Activity已經(jīng)被銷毀了,這里就會崩潰。
Anko提供了非常簡單的DSL來處理異步任務(wù),它滿足大部分的需求。它提供了一個基本的async函數(shù)用于在其它線程執(zhí)行代碼,也可以選擇通過調(diào)用uiThread的方式回到主線程。在子線程中執(zhí)行請求如下這么簡單:
async() {
Request(url).run()
uiThread { longToast("Request performed") }
}
UIThread有一個很不錯的一點就是可以依賴于調(diào)用者。如果它是被一個Activity調(diào)用的,那么如果activity.isFinishing()返回true,則uiThread不會執(zhí)行,這樣就不會在Activity銷毀的時候遇到崩潰的情況了。
假如你想使用Future來工作,async返回一個Java Future。而且如果你需要一個返回結(jié)果的Future,你可以使用asyncResult。
真的很簡單,對吧?而且比AsyncTasks更加具有可讀性。現(xiàn)在,我僅僅給請求發(fā)送了一個url,來測試我們是否可以正確接收內(nèi)容,這樣我們才能在Activity中把它畫出來。我很快會講到怎么去進行json解析和轉(zhuǎn)換成app中的數(shù)據(jù)類,但是在我們繼續(xù)之前,學(xué)習(xí)什么是數(shù)據(jù)類也是很重要的。
檢查代碼并審查url請求和包結(jié)構(gòu)的代碼。你可以運行app并且確保你可以在打印的json日志和請求完畢之后的toast。