Kotlin入門(32)網路介面訪問

来源:https://www.cnblogs.com/aqi00/archive/2018/11/07/9926505.html
-Advertisement-
Play Games

手機上的資源畢竟有限,為了獲取更豐富的信息,就得到遼闊的互聯網大海上衝浪。對於App自身,也要經常與伺服器交互,以便獲取最新的數據顯示到界面上。這個客戶端與服務端之間的信息交互,基本使用HTTP協議進行通信,即App訪問伺服器的HTTP介面來傳輸數據。HTTP介面調用在Java代碼中可不是一個輕鬆的 ...


手機上的資源畢竟有限,為了獲取更豐富的信息,就得到遼闊的互聯網大海上衝浪。對於App自身,也要經常與伺服器交互,以便獲取最新的數據顯示到界面上。這個客戶端與服務端之間的信息交互,基本使用HTTP協議進行通信,即App訪問伺服器的HTTP介面來傳輸數據。HTTP介面調用在Java代碼中可不是一個輕鬆的活,開發者若用最基礎的HttpURLConnection來編碼的話,至少要考慮以下場景的處理:
1、HTTP的請求方式是什麼,是GET還是POST還是PUT還是DELETE?
2、HTTP的連接超時時間是多少,請求應答的超時時間又是多少?
3、HTTP頭部的語言和瀏覽器信息該設置為什麼?
4、HTTP傳輸的數據內容採取的是哪種編碼方式?
5、HTTP的應答數據如果是壓縮過的,又要如何解壓?
6、HTTP的輸入輸出流需要註意哪些方面?
7、HTTP如何分塊傳輸較大的數據信息?
瞧瞧上面層出不窮的功能要求,如果開發者事必躬親逐個編碼,那可真是要累得夠嗆。因此,各種意圖取代HttpURLConnection的網路交互框架如雨後春筍般涌現出來,既有老資格的如HttpClient,又有後起之秀如Android-Async-Http、Volley、OkHttp、Retrofit等等,可謂是百花齊放、百家爭鳴。當然,這些網路框架是需要學習成本的,使用起來也不如想象中的那麼容易;它們只是在技術上各有千秋,並非終極的解決方案,往往是你方唱罷我登臺,各領風騷幾年然後歇菜。
其實HTTP交互原本無需這樣大動干戈,常見的介面調用僅僅是App往伺服器發送一串請求信息,然後伺服器返回給App一串處理結果,這種簡單的業務場景已經足夠應付大多數App的網路通信需求。所以大道至簡,Kotlin把網路交互看作是跟文件讀寫一樣的I/O操作,後端地址就像是個文件路徑,那麼請求伺服器的數據猶如讀取文件內容。文本分為文本文件和二進位文件兩種,則HTTP介面對應獲取文本數據和獲取二進位數據兩種,於是整個網路請求便簡化為數據的存跟取了。
具體到詳細的Kotlin編碼,文件對象由“File(文件路徑)”構建,而HTTP對象由“URL(網路地址)”構建,獲取介面數據則有readText和readBytes兩個方法,前者用於獲取文本形式的應答數據,後者用於二進位形式的應答數據如圖片文件、音頻文件等等。僅僅一個readText方法真的能完成繁雜的HTTP介面調用操作嗎?下麵我們通過一個具體的介面訪問案例,探討一下如何使用Kotlin代碼實現HTTP介面調用。
智能手機普遍提供了定位功能,可是系統自帶的定位服務只能獲得用戶所在的經緯度信息,而這枯燥的經緯度數字令人不知所云,肯定要把經緯度轉換為詳細的地址信息才方便用戶理解。將經緯度轉換為詳細地址,就要訪問谷歌地圖提供的地址查詢介面了,該介面的地址形如“http://maps.google.cn/maps/api/geocode/json?請求參數信息”,App把經緯度數據作文請求參數傳入,對方會返回一個包含地址信息的json串,通過解析json串即可獲得當前的詳細地址。由於訪問網路需要在分線程進行,因此介面訪問代碼必須放在doAsync代碼塊中,下麵給出根據經緯度獲取詳細地址的Kotlin代碼片段:

    private val mapsUrl = "http://maps.google.cn/maps/api/geocode/json?latlng={0},{1}&sensor=true&language=zh-CN"
    
    //位置監聽器偵聽到定位變化事件,就調用該函數請求詳細地址
    private fun setLocationText(location: Location?) {
        if (location != null) {
            doAsync {
                //根據經緯度數據從谷歌地圖獲取詳細地址信息
                val url = MessageFormat.format(mapsUrl, location.latitude, location.longitude)
                val text = URL(url).readText()
                val obj = JSONObject(text)
                val resultArray = obj.getJSONArray("results")
                var address = ""
                //解析json字元串,其中formatted_address欄位為具體地址名稱
                if (resultArray.length() > 0) {
                    val resultObj = resultArray.getJSONObject(0)
                    address = resultObj.getString("formatted_address")
                }
                //獲得該地點的詳細地址之後,回到主線程把地址顯示在界面上
                uiThread { findAddress(location, address) }
            }
        } else {
            tv_location.text = "$mLocation\n暫未獲取到定位對象"
        }
    }

    //在主線程中把定位信息連同地址信息都列印到界面上
    private fun findAddress(location: Location, address: String) {
        tv_location.text = "$mLocation\n定位對象信息如下: " +
                "\n\t時間:${DateUtil.nowDateTime}" +
                "\n\t經度:${location.longitude},緯度:${location.latitude}" +
                "\n\t高度:${location.altitude}米,精度:${location.accuracy}米" +
                "\n\t地址:$address"
    }

上述代碼看起來顯然簡明扼要,寥寥數行便搞定了完整的功能實現。如果使用Java代碼實現該功能,首先HTTP調用就得提供底層的介面訪問代碼,其次分線程請求網路又得專門寫個繼承自AsyncTask的任務處理代碼,末了Activity這邊廂還得實現該任務的完成事件,真是興師動眾、勞民傷財。由此可見Kotlin的網路交互是革命性的,方式雖然簡單,卻足以應付大部分的網路通信需求,並且運行效果與Java代碼幾無差別,例如調用地圖介面查詢地址信息,無論採用Java編碼還是Kotlin編碼,界面效果都如下圖所示。

上面利用readText方法就完成了文本數據的介面調用,當時提到了readBytes可用於獲取二進位數據如圖片文件,那麼獲取網路圖片是否也同樣方便呢?下麵我們繼續探討如何使用Kotlin代碼讀取網路圖片。
獲取網路圖片的基本流程同文本格式的介面訪問,一樣先通過URL類構建HTTP對象,然後在doAsync代碼塊中調用HTTP對象的readBytes方法獲得圖片的位元組數組。將位元組數組轉換為點陣圖對象,這在前面的文章《Kotlin入門(27)文件讀寫操作》已經加以介紹,即利用BitmapFactory工具的decodeByteArray方法實現轉換操作。轉換好的點陣圖當然可以在主線程直接顯示出來,也可以先保存為圖片文件,等到需要的時候再去讀取。前面描述如何把點陣圖保存為圖片文件時,由於Bitmap相關類並未提供簡單的圖片保存方法,因此當時保存點陣圖文件還著實頗費了一番功夫。現在保存網路圖片反而無需如此折騰,這是因為獲取網路圖片得到了位元組數組,位元組數組保存為文件可是相當方便的噢,只要調用File對象的writeBytes方法,短短一行就保存好圖片了。介紹完了網路圖片的存取流程,最終的Kotlin編碼一如既往地簡單明瞭,下麵展示了一個驗證碼動態顯示的頁面代碼:

class HttpImageActivity : AppCompatActivity() {
    private val imageUrl = "http://222.77.181.14/ValidateCode.aspx?r="

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_http_image)
        iv_image_code.setOnClickListener { getImageCode() }
        getImageCode()
    }

    //獲取網路上的圖片驗證碼
    private fun getImageCode() {
        iv_image_code.isEnabled = false
        doAsync {
            val url = "$imageUrl${DateUtil.getFormatTime()}"
            val bytes = URL(url).readBytes()
            //把位元組數組解碼為點陣圖數據
            val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
            //也可通過下麵三行代碼把位元組數組寫入文件,即生成一個圖片文件
            val path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/"
            val file_path = "$path${DateUtil.getFormatTime()}.png"
            File(file_path).writeBytes(bytes)
            //獲得驗證碼圖片數據,回到主線程把驗證碼顯示在界面上
            uiThread { finishGet(bitmap) }
        }
    }

    //在主線程中顯示獲得到的驗證碼圖片
    private fun finishGet(bitmap: Bitmap) {
        iv_image_code.setImageBitmap(bitmap)
        iv_image_code.isEnabled = true
    }
}

看到了吧,即使是完整的Activity代碼,Kotlin也只需數十行而已。倘若使用Java完成同樣的功能,除了HTTP底層與AsyncTask的編碼之外,還得補充Bitmap對象的圖片保存代碼。也就是說,Java代碼需要額外添加三個工具類的實現代碼,光光這一點,Kotlin的效率就令人贊嘆。而且,短小精悍的Kotlin代碼並未造成任何功能缺失,以上面的圖片驗證碼頁面為例,使用Java編碼和使用Kotlin編碼,最終的顯示效果都如下圖所示。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 例如:在產品表product表中欄位content值為["10"],然後在產品表中新建一個欄位product_id,提出欄位content的值10,如何實現呢? 解: update (select id,substring(content,3,instr(content,"\"]")-3) as p ...
  • 1.rpm -qa | grep mysql,查看原系統中是否有已經安裝得mysql。 註:centos7系統在安裝完成後,未安裝mysql任何版本。 2. rpm -e --nodeps mysql-libs-*********,如果有則將相關得卸載。 3.wget http://repo.mys ...
  • 小白如何學習大數據技術?大數據怎麼入門?怎麼做大數據分析?數據科學需要學習那些技術?大數據的應用前景等等問題,已成為熱門大數據領域熱門問題,以下是對新手如何學習大數據技術問題的解答~ 大數據開發學習可以按照以下內容進行學習 第一階段:JavaSE+MySql+Linux 學習內容:Java 語言入門 ...
  • 作者:天山老妖S 鏈接:http://blog.51cto.com/9291927 一、觸發器簡介 1、觸發器簡介 觸發器是和表關聯的特殊的存儲過程,可以再插入,刪除或修改表中的數據時觸發執行,比資料庫本身標準的功能有更精細和更複雜的數據控制能力。 2、觸發器的優點 A、安全性 可以基於資料庫的值使 ...
  • 歡迎大家前往 "騰訊雲+社區" ,獲取更多騰訊海量技術實踐乾貨哦~ 本文由 "騰訊雲資料庫 TencentDB" 發表於 "雲+社區專欄" 王甲坤,騰訊高級工程師、騰訊雲關係型 "資料庫MySQL" 負責人,擁有多年客戶端、資料庫研發經驗。在IOS客戶端、 "MySQL" 、 "PostgreSQL ...
  • 語句: 翻譯成中文就是: 刪除,“table1”中,id 不在此範圍的所有記錄。此範圍是,篩選出,以field1分組的,所有組別中id的最小的一個。 更直接點就是,以field1分組,選出分組中id最小的一條記錄,然後剩下的全部刪除。 理解不正確的話,請指點一二。 ...
  • http://putpan.com/fs/by4i9b7ebnbs3hbu6/ 需要IT編程經典書籍資源大合集百度網盤鏈接的加qq 2057904338,另本人願意有償帶小白學python,幫助你答疑解惑,幫助你解決問題,指導你找工作,帶你入行。相信我有人帶著你的話可以少走彎路,成功入行拿高薪。北京 ...
  • 判斷字元串是否為正整數,0開始的的數字不算。 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION [dbo].[svf_IsPositiveInteger] ( @string NVARCHAR(MAX) ) RETURN ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...