当前位置:   article > 正文

Kotlin实现Android网络请求

Kotlin实现Android网络请求

1HttpURLConnection的实现方案

网络请求时需要用户确定请求的权限,在xml中加入网络请求的权限

 <uses-permission android:name="android.permission.INTERNET"/>
  • 1

网络请求的简单实现

class HttpURLConnectionTest:AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.internet_layout)
        //第一种请求网络的方式HttpURLConnection
        get_date_by_url.setOnClickListener(){
            sendRequestWithHttpUrl()
        }

    }
    private fun sendRequestWithHttpUrl(){
        thread{
            var connection:HttpURLConnection?=null
            try{
                val response=StringBuilder()
                val url= URL("https://www.baidu.com")
                connection=url.openConnection() as HttpURLConnection
                connection.connectTimeout=8000
                connection.readTimeout=8000
                //指定请求方式
               // connection.requestMethod="Post"
                //网络输出,附带参数请求
                //val output=DataOutputStream(connection.outputStream)
                //output.writeBytes("username=admin&password=121231")
                //网络响应输入
                val input=connection.inputStream
                val reader=BufferedReader(InputStreamReader(input))
                reader.use{
                    reader.forEachLine {
                        response.append(it)
                    }
                }
                showResponse(response.toString())
            }catch (e:Exception){
                e.printStackTrace()
            }finally {
                //断开连接
                connection?.disconnect()
            }
        }
    }
    private fun showResponse(response:String){
        //此方法可以进行异步的ui界面更新
        runOnUiThread {
            response_data.text=response
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

2使用OKHttp进行网络请求

首先需要在build.gradle文件中引入OkHttp的依赖,指定版本

 //加入OKhttp的

    implementation 'com.squareup.okhttp3:okhttp:4.9.0'
  • 1
  • 2
  • 3
class HttpURLConnectionTest:AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.internet_layout)
        get_date_by_okHttp.setOnClickListener(){
            sendRequestWithOkHttp()
        }

    }
  
    private fun sendRequestWithOkHttp(){
        thread {
            try {
                val client= OkHttpClient()
                val request= Request.Builder()
                    .url("https://www.baidu.com")
                    .build()
                val response=client.newCall(request).execute()
                val responseData=response.body?.string()
                if(responseData!=null){
                    showResponse(responseData)
                }
            }catch (e:Exception){
                e.printStackTrace()
            }

        }
    }
     private fun showResponse(response:String){
        //此方法可以进行异步的ui界面更新
        runOnUiThread {
            response_data.text=response
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

注意如果使用OkHttpClient报错java.lang.ExceptionInInitializerError。可能是OKhttp包的引入版本问题,重新下载合适版本即可。

3实际场景下使用OKHttp较好的写法

在有请求且比较少的时候,直接在代码中使用OKHttp也是可以的,但是如果请求过多,不可能将请求全都放在项目代码里,所以需要对请求的方法进行一个提取抽象到工具类里面,来实现更加简单的调用。并且在进行子线程任务时,需要将结果返回到主线程,所以需要使用回调接口的方式进行数据更新

封装HttpURLRequest工具类和OKHtttp工具类

在使用HttpURLRequest时需要自定义接口


interface HttpCallbackListener {
    fun onFinish(response:String)
    fun onError(e:Exception)
}
  • 1
  • 2
  • 3
  • 4
  • 5

然后在工具类中进行方法的封装和回调接口的调用


object HttpUtil {
    fun sendHttpRequest(address:String,listener:HttpCallbackListener){
        thread {
            var connection:HttpURLConnection?=null
            try{
                val response=StringBuilder()
                val url=URL(address)
                connection=url.openConnection() as HttpURLConnection
                connection.connectTimeout=8000
                connection.readTimeout=8000
                val input=connection.inputStream
                val reader=BufferedReader(InputStreamReader(input))
                reader.use { reader.forEachLine {
                    response.append(it)
                } }
                listener.onFinish(response.toString())
            }catch (e:Exception){
                e.printStackTrace()
                listener.onError(e)
            }finally {
                connection?.disconnect()
            }
        }
    }

    //使用OkHttp的方法
    fun sendOKHttpRequest(address:String,callback:okhttp3.Callback){
        val client=OkHttpClient()
        val request=Request.Builder()
            .url(address)
            .build()
        //在enqueue的内部已经开启了子线程
        client.newCall(request).enqueue(callback)
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

使用方法


class HttpURLConnectionTest:AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.internet_layout)
        //使用工具类进行逻辑的编写
        get_date_by_util_Httpurl.setOnClickListener{
            HttpUtil.sendHttpRequest("https://www.baidu.com",object :HttpCallbackListener{
                override fun onFinish(response: String) {
                    showResponse(response)
                }

                override fun onError(e: Exception) {
                    println("在这里进行异常的处理")
                }

            })
        }
        get_date_by_util_okHttp.setOnClickListener(){
            HttpUtil.sendOKHttpRequest("https://www.baidu.com",object:Callback{
                override fun onFailure(call: Call, e: IOException) {
                    println("失败的话打印异常处理")
                }

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

            })
        }

    }
    
    private fun showResponse(response:String){
        //此方法可以进行异步的ui界面更新
        runOnUiThread {
            response_data.text=response
        }
    }

   
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

4功能更加强大的Retrofit框架

Retrofit是在OKHttp基础之上的一个综合框架,有着更好的数据请求规范和响应规范

0加入依赖库
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
 implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
  • 1
  • 2
1创建实体类,目的是为了使用GSON对返回对象进行映射
class Student(val id:Int,val name:String,val className:String) {
}
  • 1
  • 2
2创建Service接口,来处理不同请求路径的返回
interface StudentService {
    //这里指定了网站下具体的资源地址
    @GET("gete.json")
    fun getStudentInfo(): Call<List<Student>>
}
  • 1
  • 2
  • 3
  • 4
  • 5
3使用Retrofit,并处理返回数据

        use_Retrofit.setOnClickListener(){
            val retrofit=Retrofit.Builder()
            //会和Service中的地址进行组合,来确定成为一个唯一的请求地址
                .baseUrl("基础地址")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
            val studentService=retrofit.create(StudentService::class.java)
            studentService.getStudentInfo().enqueue(object:retrofit2.Callback<List<Student>>{
                override fun onResponse(
                    call: retrofit2.Call<List<Student>>,
                    response: retrofit2.Response<List<Student>>
                ) {
                    val students=response.body()
                    if(students!=null){
                        for(student in students){
                            println("输出学生的信息${student.id}等即可")
                        }
                    }
                }
                //处理异常
                override fun onFailure(call: retrofit2.Call<List<Student>>, t: Throwable) {
                    t.printStackTrace()
                }

            })
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
4一些其他请求情况的解决方案
interface StudentService {
    //这里指定了网站下具体的资源地址
    @GET("/user/Student/getStudent.json")
    fun getStudentInfo(): Call<List<Student>>
    //处理路径中带有可变参数的情况,关键词Path
    @GET("{page}/getStudent.json")
    fun getStudentInfoByPage(@Path("page") page:Int):Call<List<Student>>

    //处理Get请求时路径中带有参数的情况关键词Query
    @GET("/user/Student/getStudent.json")
    fun getStudentInfoByNameAndClassName(@Query("name") name:String,@Query("calssName") className:String):Call<List<Student>>
    //按照id删除一个学生,如果对返回值不关心,就是用Call<ResponseBody>代替
    @DELETE("/user/Student/{id}")
    fun deleteById(@Path("id") id:Int):Call<ResponseBody>
    //如果想要提交数据,直接按照对象进行提交
    @POST("user/Student")
    fun createStudent(@Body student:Student):Call<ResponseBody>

    //如果希望在请求头header中加入请求参数,就按照键值对的方式进行填充数据静态方式
    @Headers("User-Agent:okHttp","Cache-Control:max-age=0")
    @GET("地址")
    fun getStudentBy():Call<Student>
    //动态
    @GET("地址2")
    fun getStudentByDynamic(
        @Header("User-Agent") userAgent:String,
        @Header("Cache-Control") cache_control:String):Call<Student>

}
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
使用Retrofit时创建过程太过复杂,因此将其进行工具化的处理

在工具累中进行处理

object ServiceCreator {
    private const val BASE_URL="自己的基础访问地址"
    private val retrofit=Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
    //只提供一个方法即可对外返回创建的Service实例
    fun <T> create(serviceClass: Class<T>):T= retrofit.create(serviceClass)
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

使用方法

use_Retrofit.setOnClickListener(){
            /*val retrofit=Retrofit.Builder()
                .baseUrl("基础地址")
                .addConverterFactory(GsonConverterFactory.create())
                .build()*/
            
            val studentService=ServiceCreator.create(StudentService::class.java)
            studentService.getStudentInfo().enqueue(object:retrofit2.Callback<List<Student>>{
                override fun onResponse(
                    call: retrofit2.Call<List<Student>>,
                    response: retrofit2.Response<List<Student>>
                ) {
                    val students=response.body()
                    if(students!=null){
                        for(student in students){
                            println("输出学生的信息${student.id}等即可")
                        }
                    }
                }
                //处理异常
                override fun onFailure(call: retrofit2.Call<List<Student>>, t: Throwable) {
                    t.printStackTrace()
                }

            })
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/210741
推荐阅读
相关标签
  

闽ICP备14008679号