1HttpURLConnection的实现方案

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

网络请求的简单实现

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>

}

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

override fun onResponse(

call: retrofit2.Call>,

response: retrofit2.Response>

) {

val students=response.body()

if(students!=null){

for(student in students){

println("输出学生的信息${student.id}等即可")

}

}

}

//处理异常

override fun onFailure(call: retrofit2.Call>, t: Throwable) {

t.printStackTrace()

}

})

}

4一些其他请求情况的解决方案

interface StudentService {

//这里指定了网站下具体的资源地址

@GET("/user/Student/getStudent.json")

fun getStudentInfo(): Call>

//处理路径中带有可变参数的情况,关键词Path

@GET("{page}/getStudent.json")

fun getStudentInfoByPage(@Path("page") page:Int):Call>

//处理Get请求时路径中带有参数的情况关键词Query

@GET("/user/Student/getStudent.json")

fun getStudentInfoByNameAndClassName(@Query("name") name:String,@Query("calssName") className:String):Call>

//按照id删除一个学生,如果对返回值不关心,就是用Call代替

@DELETE("/user/Student/{id}")

fun deleteById(@Path("id") id:Int):Call

//如果想要提交数据,直接按照对象进行提交

@POST("user/Student")

fun createStudent(@Body student:Student):Call

//如果希望在请求头header中加入请求参数,就按照键值对的方式进行填充数据静态方式

@Headers("User-Agent:okHttp","Cache-Control:max-age=0")

@GET("地址")

fun getStudentBy():Call

//动态

@GET("地址2")

fun getStudentByDynamic(

@Header("User-Agent") userAgent:String,

@Header("Cache-Control") cache_control:String):Call

}

}

使用Retrofit时创建过程太过复杂,因此将其进行工具化的处理

在工具累中进行处理

object ServiceCreator {

private const val BASE_URL="自己的基础访问地址"

private val retrofit=Retrofit.Builder()

.baseUrl(BASE_URL)

.addConverterFactory(GsonConverterFactory.create())

.build()

//只提供一个方法即可对外返回创建的Service实例

fun create(serviceClass: Class):T= retrofit.create(serviceClass)

}

使用方法

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

override fun onResponse(

call: retrofit2.Call>,

response: retrofit2.Response>

) {

val students=response.body()

if(students!=null){

for(student in students){

println("输出学生的信息${student.id}等即可")

}

}

}

//处理异常

override fun onFailure(call: retrofit2.Call>, t: Throwable) {

t.printStackTrace()

}

})

}

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: