在Android中,使用Kotlin的 API請求簡易方法

原文標題:API request in Android the easy way using Kotlinandroid

原文連接:http://antonioleiva.com/api-request-kotlin/git

原文做者:Antonio Leiva(http://antonioleiva.com/about/github

原文發佈:2015-07-21編程

 

Kotlin是功能很是強大的編程語言,其目標是利用較少的模板(boilerplate)編寫更多的代碼。尤爲是在Android開發中。除了編程語言自身和它的類以外,Kotlin還爲已有的Java類提供一組好用的擴展。這個例子是請求API和下載結果的方法。api

 

我知道已經有許多不一樣的庫能夠幫助咱們作這些工做,而且因Kotlin與Java的互用性,它也能使用這些庫。可是,咱們有時候僅僅由於大的庫更簡單、不易出錯,對於小需求也用大庫。app

 

API請求:Java 與 Kotlin對比

 

我總喜歡把這兩種語言進行對比,看看堅持使用Java咱們會錯過什麼。從URL恢復JSON的典型代碼是這樣:異步

 

 1 try {
 2     URL url = new URL("<api call>");
 3  
 4     urlConnection = (HttpURLConnection) url.openConnection();
 5     urlConnection.setRequestMethod("GET");
 6     urlConnection.connect();
 7  
 8     InputStream inputStream = urlConnection.getInputStream();
 9     StringBuffer buffer = new StringBuffer();
10     if (inputStream == null) {
11         // Nothing to do.
12         return null;
13     }
14     reader = new BufferedReader(new InputStreamReader(inputStream));
15  
16     String line;
17     while ((line = reader.readLine()) != null) {
18         buffer.append(line + "\n");
19     }
20  
21     if (buffer.length() == 0) {
22         return null;
23     }
24     result = buffer.toString();
25 } catch (IOException e) {
26     Log.e("Request", "Error ", e);
27     return null;
28 } finally{
29     if (urlConnection != null) {
30         urlConnection.disconnect();
31     }
32     if (reader != null) {
33         try {
34             reader.close();
35         } catch (final IOException e) {
36             Log.e("Request", "Error closing stream", e);
37         }
38     }
39 }

 

Kotlin標準庫爲URL類提供了擴展函數,避免咱們編寫全部代碼。前面的代碼能夠轉換爲:async

 

1 val result = URL("<api call>").readText()

 

對於大量的響應,不建議使用這個函數,可是在大多數狀況下,它是足夠了。若是不這樣,還有許多其餘有趣的擴展函數,如:BufferedReader.forEachLine(),它產生行Sequence,讓咱們用它們中任何一個一塊兒作些事。或是,你能夠經過BufferedReader.lineSequence()獲得原始的Sequence<String>。這時,你可以執行Sequence容許的不一樣轉換中的任何一種,如:過濾、排序、映射等等。編程語言

 

異步調用

 

如你所知,主線程是負責UI呈現和交互的,咱們不該該因其它運行時間長的任務阻塞它,這將會影響UI性能。在HTTP請求狀況下, Android SDK甚至經過拋出一個異常來阻止咱們這麼作。在Android典型的解決方案是使用AsyncTaskAsyncTask有一個doInBackground抽象方法,其在另個線程中執行。ide

 

除了讓AsyncTask正常工做很難這一事實外,因爲它自身帶來了許多問題,使得經過它擴展建立一個新類、在onDestroy中終止它等等,都是很乏味。這個(你可能須要更多的檢查以免崩潰)很是簡單的版本將是:

 

 1 @Override protected void onCreate(Bundle savedInstanceState) {
 2     super.onCreate(savedInstanceState);
 3  
 4     task = new AsyncTask<Void, Void, String>() {
 5         @Override protected String doInBackground(Void... params) {
 6             return requestFromServer("<api call>");
 7         }
 8  
 9         @Override protected void onPostExecute(String s) {
10             if (!isFinishing() && !isCancelled()) {
11                 Log.d("Request", s);
12                 Toast.makeText(ExampleActivity.this, "Request performed", Toast.LENGTH_LONG).show();
13             }
14         }
15     };
16 }
17  
18 @Override protected void onDestroy() {
19     super.onDestroy();
20  
21     if (task != null) {
22         task.cancel(true);
23         task = null;
24     }
25 }

 

這實在不清晰也不直觀。當咱們在Android中用Kotlin開發時,咱們不能忘記Anko庫。它主要目的是提供DSL方式用代碼來建立佈局,而不是用XML。我實際使用過XML,因此我如今不使用它了,可是它仍是包括一整套很是有用的特性。特別對異步任務有些小的DSL。這樣在Kotlin中,前面的代碼可以減小爲:

 

1 async {
2     val result = URL("<api call>").readText()
3     uiThread { 
4         Log.d("Request", result)
5         longToast("Request performed") 
6     }
7 }

 

實際上,你有async函數,它將在另外一個線程中執行代碼,並由uiThread給出返回主線的機會。asyncContext的擴展函數實現,且使用它弱應用,因此不會阻止GC釋放內存。

 

uiThread優點的方面是它依據使用類,以用不一樣的方式來實現。若是咱們從Activity中調用它,假設actiivity.isFinishing()返回trueuiThread代碼是不會執行的,而且在此狀況下不會崩潰。

 

假設你要用future,Async返回Java Future。若是你須要返回future結果,就能夠用asyncResult

 

你還可以用你本身的執行器:

 

1 val executor = Executors.newScheduledThreadPool(4)
2 async(executor) {
3     // Some task
4 }

 

總結

 

用幾行代碼,咱們從一個很是典型的操做獲得相同(若是沒有更好的話)的結果,如:調用一個API,以String變量獲得結果。隱藏在這些擴展函數背後有許多有趣的代碼,因此我建議去重讀Kotlin和Anko源代碼,看看在幕後都作了什麼。

 

記住從我寫的書《Android開發者的Kotlin》中,你可以學習到Kotlin的這點以及許多其它能力,你將經過從0開始建立Android APP學習Kotlin。

相關文章
相關標籤/搜索