Android-Kotlin-網(wǎng)絡(luò)

Android上發(fā)送HTTP請(qǐng)求,一般有兩個(gè)方式:HttpURLConnection和HttpClient。HttpClient由于存在API數(shù)量多,擴(kuò)展困難缺點(diǎn),Android6.0開始HttpClient的功能完全移除,被廢棄。

Android 9.0開始,應(yīng)用程序默認(rèn)值允許使用HttpS類型的網(wǎng)絡(luò)請(qǐng)求。如果測(cè)試想請(qǐng)求Http的請(qǐng)求,需要配置network-security-config

進(jìn)行網(wǎng)絡(luò)請(qǐng)求,請(qǐng)先配置權(quán)限:<uses-permission android:name="android.permission.INTERNET" />

1.純HttpURLConnection進(jìn)行數(shù)據(jù)請(qǐng)求

private fun doRequestWithHttpURLConnection(){
    thread {
        var connection:HttpURLConnection?=null
        val response = StringBuilder()
        val url = URL("https://www.baidu.com/")
        connection = url.openConnection() as HttpURLConnection
        connection.connectTimeout = 8000
        connection.readTimeout = 8000
        val inputStream = connection.inputStream
        val reader = BufferedReader(InputStreamReader(inputStream))

        reader.use {
            reader.forEachLine {
                response.append(it)
            }
        }

        showResponse( response.toString())

    }
}


 private fun showResponse(content: String) {
        runOnUiThread {
            responseText.text = content
        }

    }

注意:網(wǎng)絡(luò)請(qǐng)求需要放置在子線程,刷新UI需要在UI線程

2.使用OKHttp

在開源盛行的今天,網(wǎng)絡(luò)方面有很多開源的框架,其中OkHttp是比較優(yōu)秀的。

implementation 'com.squareup.okhttp3:okhttp:4.9.3'

使用OkHttp需要添加這個(gè)依賴,添加之后會(huì)自動(dòng)加載兩個(gè)庫一個(gè)是OkHttp庫,一個(gè)是Okio庫,后者是前者通信的基礎(chǔ)。

  fun sendOkHttpRequest(address:String,callback:Callback){
        val client=OkHttpClient()
        val request=Request.Builder()
            .url(address)
            .build()
        client.newCall(request).enqueue(callback)
    }

//在activity調(diào)用
     sendOkHttpRequest("https://www.baidu.com/", object :Callback {
            override fun onFailure(call: Call, e: IOException) {
                TODO("Not yet implemented")
            }

            override fun onResponse(call: Call, response: Response) {
                val string = response.body?.string()
                showResponse(string)
            }

        })

3.Retrofit 庫的使用

retrofit庫,是在okHttp的基礎(chǔ)上繼續(xù)封裝的庫,是目前最好的網(wǎng)絡(luò)框架。OkHttp側(cè)重在底層通信的實(shí)現(xiàn),Retrofit側(cè)重是上層接口的封裝。

常用的請(qǐng)求注解:

  • @GET :請(qǐng)求服務(wù)器啥的數(shù)據(jù)

  • @POST:用于向服務(wù)器提交數(shù)據(jù)

  • @PUT:修復(fù)服務(wù)器上的數(shù)據(jù)

  • @DELETE:刪除服務(wù)器上的數(shù)據(jù)

object RetrofitCreator {

    private const val BASE_URL="https://vsapi.meishesdk.com"
    private val retrofit=Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build()
    fun <T> create(retrofitClass:Class<T>):T= retrofit.create(retrofitClass)
    inline fun <reified T> create(): T = create(T::class.java)
}

定義一個(gè)單例的Retrofit的創(chuàng)建類

//get 請(qǐng)求傳參數(shù)
@GET("/api/authorization/ST/current")
fun getSTLicFileInfo(@Query("appId") appId:String): Call<LicenseInfo>

定義一個(gè)接口,通過@Query來傳遞參數(shù),返回一個(gè)對(duì)象。

val appService = RetrofitCreator.create<AppService>()
appService.getSTLicFileInfo(App.getAppId()).enqueue(object : Callback<LicenseInfo>{
    override fun onResponse(call: Call<LicenseInfo>, response: Response<LicenseInfo>) {
        Log.d("test","onResponse")
    }

    override fun onFailure(call: Call<LicenseInfo>, t: Throwable) {
        Log.d("test","onFailure")
    }

})

使用的時(shí)候通過上面的方式就行調(diào)用

//get請(qǐng)求,通過path 來實(shí)現(xiàn)分頁接口
@GET("{page}/data.json")
fun getData(@Path("page") page:Int):Call<List<LicenseInfo>>

通過使用Path來定義分頁請(qǐng)求的接口

@DELETE("data/{id}")
fun deleteLic(@Path("id") id:String):Call<ResponseBody>

刪除一條數(shù)據(jù),返回值是ResponseBody,表示客戶端對(duì)于服務(wù)器響應(yīng)的數(shù)據(jù)不關(guān)心,也不解析。

@POST("data/create")
fun createData(@Body data:Data):Call<ResponseBody>

post 請(qǐng)求通過@Body來提交Data類型的數(shù)據(jù)

//靜態(tài)傳Header
@Headers("User-Agent:okhttp","Cache-Control:max-age=0")
@GET("data.json")
fun getData():Call<Data>

//動(dòng)態(tài)傳Header
@GET("data.json")
fun getData( @Header("Cache-Control") cacheControl:String):Call<Data>

帶著Header來請(qǐng)求,這個(gè)形式是靜態(tài)的傳遞Header,如果希望動(dòng)態(tài)傳遞Header需要用到

4.Retrofit實(shí)現(xiàn)下載文件

 //動(dòng)態(tài)url實(shí)現(xiàn)下載 用于小文件下載
 @GET
 fun downloadFile(@Url url:String):Call<ResponseBody>

通過@Url來實(shí)現(xiàn)動(dòng)態(tài)url來下載文件,由于全部寫入內(nèi)內(nèi)存,所以不能下載大文件,否則會(huì)OOM

val create = RetrofitCreator.create<AppService>()
val downloadFile = create.downloadFile("http://196.168.1.200/text.txt")
downloadFile.enqueue(object : retrofit2.Callback<ResponseBody>{
    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
       if (response.isSuccessful){
           val writtenToDisk: Boolean = writeResponseBodyToDisk(response.body())
       }
    }

    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
        TODO("Not yet implemented")
    }

})
//將數(shù)據(jù)寫入文件
private boolean writeResponseBodyToDisk(ResponseBody body) {  
    try {
        // todo change the file location/name according to your needs
        File futureStudioIconFile = new File(getExternalFilesDir(null) + File.separator + "Icon.png");

        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            byte[] fileReader = new byte[4096];

            long fileSize = body.contentLength();
            long fileSizeDownloaded = 0;

            inputStream = body.byteStream();
            outputStream = new FileOutputStream(futureStudioIconFile);

            while (true) {
                int read = inputStream.read(fileReader);

                if (read == -1) {
                    break;
                }

                outputStream.write(fileReader, 0, read);

                fileSizeDownloaded += read;

                Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
            }

            outputStream.flush();

            return true;
        } catch (IOException e) {
            return false;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }
        }
    } catch (IOException e) {
        return false;
    }
}

如果是大文件下載

    @Streaming
    @GET
    fun downloadBigFile(@Url url:String):Call<ResponseBody>

下載大文件只需要添加@Streaming的方式來實(shí)現(xiàn)大文件下載

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容