首页 > 其他分享 >使用Kotlin+协程+Flow+Retrofit+OkHttp搭建一套网络请求工具

使用Kotlin+协程+Flow+Retrofit+OkHttp搭建一套网络请求工具

时间:2024-08-28 11:28:20浏览次数:6  
标签:map 协程 String Kotlin Flow 接口 println fun com

文章目录

一、前言

  1. 怎么快速找调试接口?怎么快速找一个网络请求工具?
    很多人马上想到Retrofit + Okhttp 早起还有 HttpURLConnection 和 Volley但是 这大家常用的都是集成在Android程序里面,需 要安装运行在android设备里面,大多数需要触发按钮点击 才能调用访问接口,我们大多数情况下是需要 先看到数据结构正常,符合要求了,才进行开始写网络接口部分,特别是在自己研究某些网络接口,而这时候又没有类似可以调试的文档的时候

  2. 网络请求工具PC版上有好多工具。类似 Swagger 文档 , ApiFox ,或者其他在线网页请求工具?为什么又不用
    其实这个问题是,有类似网络调试接口文档是最好的,有时候没有的情况下或者说这些工具,大大小小都不是能完全满足某些需求,特别是 post的各种方式,或者put等不常用的请求方式

  3. 那 Retrofit + Okhttp 解耦的这么好用,可以搭建起来在PC上直接运行吗?可以的,不用那么麻烦的要查看一个接口数据,需要写好运行安装到手机里面,再点击按钮,这个过程大概需要 一分钟左右,如果写好代码直接调用,随时可以调用,不是节省很多时间。

  4. 这样做有什么好处?
    (1) 方便调试,方便快速查看接口数据,节省很多时间
    (2) 可以快速用PC写好的网络部分拷贝到Android工程项目里面用
    (3) 在没有调试接口文档,调用第三方Api或者研究其他接口时快速调用下接口后看内容
    (4) 网络抓包,找其他资源情况下,可以快速抓取到

二、搭建Java工程

1.打开Android Studio 建一个Android 工程

2.修改该工程的build.gradle文件为Java 工程,并配置如下:

plugins {
    id 'java-library'
    id 'kotlin'
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:1.7.0"
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
    implementation 'com.squareup.okhttp3:okhttp:4.9.3'
    implementation 'com.squareup.okio:okio:2.10.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

    implementation 'com.google.protobuf:protobuf-java:3.5.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
}

3. 搭建一个 RetrofitUtils 请求工具类,这都是常规操作了,如下

class RetrofitUtils private constructor(private val baseUrl: String) {

    companion object {
        var instance: RetrofitUtils? = null

        fun getInstance(baseUrl: String) = instance ?: synchronized(this) {
            instance ?: RetrofitUtils(baseUrl).also { instance = it }
        }
    }

    private inline val retrofit: Retrofit
        get() {
            val logging = HttpLoggingInterceptor()
            val timeout = 30000L
            val okHttpClient = OkHttpClient.Builder()
                .addInterceptor(HeaderInterceptor())
                .addInterceptor(logging)
//                .addInterceptor(RetrofitClient.BaseUrlInterceptor())
                .callTimeout(timeout, TimeUnit.MILLISECONDS)
                //设置连接超时
                .connectTimeout(timeout, TimeUnit.MILLISECONDS)
                //设置从主机读信息超时
                .readTimeout(timeout, TimeUnit.MILLISECONDS)
                //设置写信息超时
                .writeTimeout(timeout, TimeUnit.MILLISECONDS)
                .retryOnConnectionFailure(true)//设置出现错误进行重新连接。
                .build();
            return Retrofit.Builder()
                .client(okHttpClient)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(baseUrl)
                .build()
        }

    fun <T> create(service: Class<T>?): T {
        if (service == null) {
            throw RuntimeException("Api service is null!")
        }
        return retrofit.create(service)!!
    }
}

4.建一个 NetWorkAPi 作为 Retrofit 请求接口:

interface NetWorkAPi {

   //示例post 请求
   @FormUrlEncoded
   @POST("https://www.wanandroid.com/user/register")
   suspend fun register(
       @Field("username") username: String,
       @Field("password") password: String,
       @Field("repassword") repassword: String
   ): String

   // 示例get 请求
   @GET("article/list/0/json")
   suspend fun getHomeList(): String

   // 示例get 请求2
   @GET("article/list/{path}/json")
   suspend fun getHomeList22(@Path("path") page: Int): HomeData

   /************************* 以下只 示例写法,接口调不通,因为找不到那么多 公开接口  全是 Retrofit的用法 来测试 *****************************************************/


//    @FormUrlEncoded
   @Headers("Content-Type: application/x-www-form-urlencoded")  //todo 固定 header
   @POST("https://xxxxxxx")
   fun post1(@Body body: RequestBody): String

//    @FormUrlEncoded
   @Headers("Content-Type: application/x-www-form-urlencoded")
   @POST("https://xxxxxxx22222")
   fun post12(@Body body: RequestBody, @HeaderMap map: Map<String, String>): String //todo  HeaderMap 多个请求头部自己填写
}

5.建一个 WXRepository 为了和Android 里面保持一致,可以直接拿过去用

class WXRepository private constructor() {

    companion object {
        val instance by lazy { WXRepository() }
    }

    private val baseUrl = "https://www.wanandroid.com/"
    private val api = RetrofitUtils.getInstance(baseUrl).create(NetWorkAPi::class.java)

    fun getHomeList() {
        runBlocking {
            // 主协程下面执行 flow 异步请求
            flow {
                emit(api.getHomeList())
            }.flowOn(Dispatchers.IO).catch {
                println(it.parseErrorString()) // 打印异常信息
            }.collect {
                println("网络返回结果:$it") // 打印异常信息
            }
            delay(10000) // 让程序主进程 在打印前不结束
        }
    }

    fun getHomeList22() {
        runBlocking {
            // 主协程下面执行 flow 异步请求
            flow {
                emit(api.getHomeList22(1))
            }.flowOn(Dispatchers.IO).catch {
                println(it)
                println(it.parseErrorString()) // 打印异常信息
            }.collect {
                it.data?.datas?.forEachIndexed { i, it ->
                    println("第$i 条 : ${it.title}") // 打印异常信息
                }
            }
            delay(10000) // 让java工程 程序主进程 在打印前不结束
        }
    }

    fun register(username: String, password: String, repassword: String) {
        runBlocking {
            flow {
                emit(api.register(username, password, repassword))
            }.flowOn(Dispatchers.IO).catch {
                println(it)
                println(it.parseErrorString()) // 打印异常信息
            }.collect {
                println(it)
            }
        }
    }

    /************************* 以下只 示例写法,接口调不通,因为找不到那么多 公开接口  全是 Retrofit的用法 来测试 *****************************************************/

    fun post1() {
        runBlocking {
            flow {
                val map = mutableMapOf<String, Any>()
                map["AAAAAA"] = "AAAAAA"
                map["BBBBBB"] = 1
                map["CCCCCC"] = true
                map["DDDDDD"] = 30.00f
                emit(api.post1(RequestBodyWrapper(Gson().toJson(map))))
            }.flowOn(Dispatchers.IO).catch {
                println(it)
                println(it.parseErrorString()) // 打印异常信息
            }.collect {
                println(it)
            }
        }
    }


    fun post12() {
        runBlocking {
            flow {
                val map = mutableMapOf<String, Any>()
                map["AAAAAA"] = "AAAAAA"
                map["BBBBBB"] = 1
                map["CCCCCC"] = true
                map["DDDDDD"] = 30.00f

                val headerMap = mapOf(
                    "Cookie" to "uab_collina=171755326751237298573402; tfstk=fFqEGyx3iMIEHdYy8fir_5GQozgKVDffUuGSE82odXcnd0awZ5V9FXiIAPlzs5lhp6CLa3Van4c7V09LWSwDAk_KV3-K20ffGisXpJn-qHga3LOpSxMhVYcnqYuGorffGis_pJn-qsa52bcgOYhMKYc3Zh0i6Y8oqX0ksFDmsbmoq7xGjxM2xU0oKdc9M402bY3h9NU_OKjk2plbKf-2BPkMqjsxT3Y7bvRjZJYDq3qZL2ESMIWRh2auHqEQQg-tA-zijYrRnUlruzqIjkfGmV3uz7DTW_8rgz2QkAqcFEh_bXNuYVXX04igcqm35NCIPDkoxqUOeeGur-rqAW19qXa4I5ubfCtjmrFa4qmc4XO-ISE82yRkr2xSQj6NI96RN__qDt2vyU3B6AlfK9YkrIKXVer5pUL-RaDZG9XA.; uag=7aed8d4dcb46b3eaa0e85f86b21df22e; ylogin=4024975; folder_id_c=10376791; phpdisk_info=WGhSYARkBz8BOgRjDmEEV1QwAAsAaAVlAzcDYw8xCjlTZFdjUjcDPFJiUAkMYFU9VD0NP109BWIPbgQxATMKPVg5UjUEMgdtAWAENQ5jBG5UZgA6AGoFawM4A2oPPwptU2FXYlJiAzxSZ1BhDF9VPlQzDThdNAVqDz0EZwExCj9Yb1Ji; PHPSESSID=pbba5e4111h3fk7om64mdgf4sbd0c6lm; __tins__21412745=%7B%22sid%22%3A%201717724688543%2C%20%22vd%22%3A%2012%2C%20%22expires%22%3A%201717727331949%7D; __51cke__=; __51laig__=12",
                    "Host" to "up.SSSSSwxxxoozooo.com",
                    "Origin" to "http://AAAAAAAAup.wxssosdsozosdoo.com",
                    "Referer" to "http://AAAAAAAup.wodsdsdsdsdosddszooo.com/mydisk.php?item=files&action=index&u=4024975"
                )

                emit(api.post12(RequestBodyWrapper(Gson().toJson(map)), headerMap))
            }.flowOn(Dispatchers.IO).catch {
                println(it)
                println(it.parseErrorString()) // 打印异常信息
            }.collect {
                println(it)
            }
        }
    }
}

6.新建一个 WXMainTool.kt 类作为 主程序调用main 函数入口:

fun main() {
//    WXRepository.instance.getHomeList()
    WXRepository.instance.getHomeList22()
//    WXRepository.instance.register("WXXXXXXXXXX","1212121","1212121")

}

三、运行调用接口

这里运行 WXRepository.instance.getHomeList22() ,而调用 WXRepository中的

fun getHomeList22() {
   runBlocking {
       // 主协程下面执行 flow 异步请求
       flow {
           emit(api.getHomeList22(1))
       }.flowOn(Dispatchers.IO).catch {
           println(it)
           println(it.parseErrorString()) // 打印异常信息
       }.collect {
           it.data?.datas?.forEachIndexed { i, it ->
               println("第$i 条 : ${it.title}") // 打印异常信息
           }
       }
       delay(10000) // 让java工程 程序主进程 在打印前不结束
   }
}

标签:map,协程,String,Kotlin,Flow,接口,println,fun,com
From: https://blog.csdn.net/hexin5213578/article/details/141636090

相关文章

  • 洛谷 P3128 [USACO15DEC] Max Flow P
    洛谷P3128[USACO15DEC]MaxFlowP题意给定一棵\(n\)个点的树,给定\(k\)个点对\((u,v)\),把\(u\)到\(v\)路径上所有点的点权加一,最后求最大点权。思路树上差分模版。维护\(a_i\)表示每个点到根的加法标记。对于每个点对\((u,v)\),把\(a_u\),\(a_v\)加一,\(a_{LCA......
  • 第一章 协程
    协程&asyncio&异步编程的>背景为什么要学?越来越多的学生都来问async异步相关问题,并且这一部分的知识点不太容易学习(异步非阻塞、asyncio)异步相关话题和框架越来越多,例如:tornado、fastapi、django3.xasgi、aiohttp都在异步->提升性能。如何讲解?第一部分:协程。......
  • AntFlow系列教程之流程提交
    AntFlow为笔者基于activiti深度定制的一款简单易用的开源低代码流程引擎,类似钉钉工作流.详细介绍可以查看企业级仿钉钉低代码工作流引擎开源啦.项目刚开源不久,希望喜欢的大佬们多点赞关注.后面除了会写文章介绍AntFlow的使用,还会写文章介绍activiti8的使用.流程的操......
  • 【Kotlin设计模式】Kotlin实现外观模式
    前言外观模式(FacadePattern)是一种结构型设计模式,旨在为子系统中的一组接口提供一个统一的接口。外观模式定义了一个高层接口,使得这一子系统更加容易使用。它将复杂的子系统封装在一个简单的接口后面,从而降低了客户端的复杂性。实现我们以银行APP业务举个例子,其中包......
  • 如何使用TensorFlow构建AI模型
    TensorFlow已成为构建机器学习模型最受欢迎的框架之一。无论你是初学者还是经验丰富的数据科学家,了解如何使用TensorFlow构建AI模型对充分利用机器学习的潜力至关重要。本指南将引导你逐步创建TensorFlowAI模型,从基础知识到更高级的概念,确保你拥有坚实的基础。了解Te......
  • 从Flow小白到专家,Winter '25让流程自动化更简单!
    Salesforce平台每月提供超过1万亿次自动化服务,每月可节省超1090亿小时,预计为客户创造超2万亿美元的商业价值。这是一组不可思议的数字,充分展现了软件自动化的力量。Flow是整个Salesforce平台自动化的未来,一直在将大量资源用于开发Flow创新。本次Winter'25中自然也少不了Flow的......
  • 计算机毕业设计Spark+Tensorflow股票推荐系统 股票预测系统 股票可视化 股票数据分析
    1. 需求分析基于Spark的股票大数据分析及可视化系统是一个利用Spark分布式计算框架进行股票市场数据处理、分析和可视化的系统。它能够处理大规模的实时股票数据,包括股票价格、交易量、市场指标等,提供实时数据处理、数据可视化与展示和并提供相应决策支持。因此基于Spark的......
  • TensorFlow实现Softmax回归
    原理模型相比线性回归,Softmax只多一个分类的操作,即预测结果由连续值变为离散值,为了实现这样的结果,我们可以使最后一层具有多个神经元,而输入不变,其结构如图所示:为了实现分类,我们使用一个Softmax操作,Softmax函数能够将未规范化的预测变换为非负数并且总和为1,同时让模型保持可......
  • 在Kotlin中使用Spark SQL的UDF和UDAF函数
    1.项目结构与依赖1.1项目依赖使用gradle:在项目的build.gradle.kts添加dependencies{  implementation("org.apache.spark:spark-sql_2.12:3.3.1")}使用maven:在模块的pom.xml中添加<dependency><groupId>org.apache.spark</groupId>......
  • 用TensorFlow实现线性回归
    说明本文采用TensorFlow框架进行讲解,虽然之前的文章都采用mxnet,但是我发现tensorflow提供了免费的gpu可供使用,所以果断开始改为tensorflow,若要实现文章代码,可以使用colaboratory进行运行,当然,如果您已经安装了tensorflow,可以采用python直接运行。贡献学习时采取动手学深度学......