Kotlin实现Android网络请求

1HttpURLConnection的实现方案

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

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

网络请求的简单实现

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

2使用OKHttp进行网络请求

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

 //加入OKhttp的

    implementation 'com.squareup.okhttp3:okhttp:4.9.0'
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
        }
    }
}

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

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

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

封装HttpURLRequest工具类和OKHtttp工具类

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


interface HttpCallbackListener {
    
    
    fun onFinish(response:String)
    fun onError(e:Exception)
}

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


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

使用方法


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

   
}

4功能更加强大的Retrofit框架

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

0加入依赖库

implementation 'com.squareup.retrofit2:retrofit:2.6.1'
 implementation 'com.squareup.retrofit2:converter-gson:2.6.1'

1创建实体类,目的是为了使用GSON对返回对象进行映射

class Student(val id:Int,val name:String,val className:String) {
    
    
}

2创建Service接口,来处理不同请求路径的返回

interface StudentService {
    
    
    //这里指定了网站下具体的资源地址
    @GET("gete.json")
    fun getStudentInfo(): Call<List<Student>>
}

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

            })
        }

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>

}
    
}

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

使用方法

扫描二维码关注公众号,回复: 15522328 查看本文章
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()
                }

            })
        }

猜你喜欢

转载自blog.csdn.net/m0_56184347/article/details/129731961