Android-Kotlin-网络

Android上发送HTTP请求,一般有两个方式:HttpURLConnection和HttpClient。HttpClient由于存在API数量多,扩展困难缺点,Android6.0开始HttpClient的功能完全移除,被废弃。

Android 9.0开始,应用程序默认值允许使用HttpS类型的网络请求。如果测试想请求Http的请求,需要配置network-security-config

进行网络请求,请先配置权限:

1.纯HttpURLConnection进行数据请求

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
        }

    }

注意:网络请求需要放置在子线程,刷新UI需要在UI线程

2.使用OKHttp

在开源盛行的今天,网络方面有很多开源的框架,其中OkHttp是比较优秀的。

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

使用OkHttp需要添加这个依赖,添加之后会自动加载两个库一个是OkHttp库,一个是Okio库,后者是前者通信的基础。

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

//在activity调用
     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的基础上继续封装的库,是目前最好的网络框架。OkHttp侧重在底层通信的实现,Retrofit侧重是上层接口的封装。

常用的请求注解:

  • @GET :请求服务器啥的数据

  • @POST:用于向服务器提交数据

  • @PUT:修复服务器上的数据

  • @DELETE:删除服务器上的数据

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)
}

定义一个单例的Retrofit的创建类

//get 请求传参数
@GET("/api/authorization/ST/current")
fun getSTLicFileInfo(@Query("appId") appId:String): Call<LicenseInfo>

定义一个接口,通过@Query来传递参数,返回一个对象。

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")
    }

})

使用的时候通过上面的方式就行调用

//get请求,通过path 来实现分页接口
@GET("{page}/data.json")
fun getData(@Path("page") page:Int):Call<List<LicenseInfo>>

通过使用Path来定义分页请求的接口

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

删除一条数据,返回值是ResponseBody,表示客户端对于服务器响应的数据不关心,也不解析。

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

post 请求通过@Body来提交Data类型的数据

//静态传Header
@Headers("User-Agent:okhttp","Cache-Control:max-age=0")
@GET("data.json")
fun getData():Call<Data>

//动态传Header
@GET("data.json")
fun getData( @Header("Cache-Control") cacheControl:String):Call<Data>

带着Header来请求,这个形式是静态的传递Header,如果希望动态传递Header需要用到

4.Retrofit实现下载文件

 //动态url实现下载 用于小文件下载
 @GET
 fun downloadFile(@Url url:String):Call<ResponseBody>

通过@Url来实现动态url来下载文件,由于全部写入内内存,所以不能下载大文件,否则会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")
    }

})
//将数据写入文件
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的方式来实现大文件下载

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值