# Android网络库 **Repository Path**: hitcoder/network ## Basic Information - **Project Name**: Android网络库 - **Description**: Android网络访问库,Retrofit+OkHttp+Kotlin,主要目的是对于kotlin协程访问网络接口的支持 - **Primary Language**: Kotlin - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 1 - **Created**: 2020-08-07 - **Last Updated**: 2022-03-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Android通用库 [ ![Download](https://api.bintray.com/packages/hit/maven/network/images/download.svg?version=1.0.0) ](https://bintray.com/hit/maven/network/1.0.0/link) [![](https://jitpack.io/v/com.gitee.hitcoder/network.svg)](https://jitpack.io/#com.gitee.hitcoder/network) #### 介绍 Android通用库,对常用组件和框架进行封装,用以提升开发效率. 支持:网络接口日志打印、文件上传、下载进度监听、断点下载等功能。 #### 软件架构 network library 采用Retrofit+OkHttp+Kotlin的形式进行封装,主要目的是对于kotlin协程访问网络接口的支持。 #### 安装教程 1. 使用jcenter仓库 ``` implementation 'cn.hitcoder.android:network:1.0.0' ``` 2. 使用jitpack仓库: - 在项目的build.gradle文件中配置jitpack仓库 ``` maven { url 'https://jitpack.io' } ``` - 在需要使用网络框架的module中引入依赖 ``` implementation 'com.gitee.hitcoder:network:0.0.1' ``` #### 使用说明 1. 在module中定义网络接口 ``` interface NetworkInterface { /** * 用户登录接口 */ @Headers("Content-Type: application/json", "Accept: application/json") @POST("basic/user/login") fun login(@Body route: RequestBody?): Call> /** * 上传文件 */ @Multipart @POST("/upload") fun upload(@Part file: List?): Call } ``` 2. 定义网络接口访问对象(支持多个) ``` val net = NetWorkApi.Builder .setBaseUrl(YOUR_BASL_URL) .setErrorHandler { when (it) { //匹配不同的服务器返回值类型 is NetResponse<*> -> { if (!TextUtils.equals(it.status.code, "1")) { throw ServerException(-1, "网络接口调用失败") } } } } .setCallAdapterFactory() //设置CallAdapterFactory .setConverterFactory() //设置ConverterFactory .addInterceptor() //设置Interceptor .setDebug(true) //打印接口访问日志 .setTimeout(30) //设置超时时间 .build() //定义扩展函数,执行框架内封装的同步执行扩展函数,传入自定义errorHandler fun Call.exe() = executeEx(net.appErrorHandler) //定义扩展函数,执行框架内封装的异步执行扩展函数,传入自定义errorHandler fun Call.enQ(callback: (code: Int, message: String, data: T?) -> Unit) = enqueueEx(callback, net.appErrorHandler) /** * 封装请求参数 */ fun requestBody(params: T): RequestBody { val netRequest = NetRequest("03815d7a-ee06-48de-8893-c6c4aa0cc835", "", "", "", params) val jsonString = Gson().toJson(netRequest) return jsonString.toJsonRequestBody() } ``` 3. 访问网络接口示例 访问普通网络接口 ``` val loginRequest = LoginRequest("yangqinhe", "1234567", "android") //同步执行 launch(Dispatchers.IO) { val loginData = net.getService(NetworkInterface::class.java) .login(requestBody(loginRequest)) .exe() withContext(Dispatchers.Main) { textView.text = loginData.toString() Log.e("TAG", loginData.toString()) } } //异步执行 val enQ = net.getService(NetworkInterface::class.java) .login(requestBody(loginRequest)) .enQ { code, message, data -> textView.text = "code: $code message: $message data: $data" Log.e("YQH", "code: $code message: $message data: $data") } //取消 enQ.cancel() ``` 文件上传 ``` launch(Dispatchers.IO) { val file = File(getExternalFilesDir(null)?.absolutePath, "1.jpg") val file2 = File(getExternalFilesDir(null)?.absolutePath, "2.jpg") Log.e("TAG", "totalLength : ${file.length() + file2.length()}") val executeExa = net.getRequestProgressService(NetworkInterface::class.java) { read, total, done -> textView.text = Thread.currentThread().name + " 进度: " + read * 100 / total Log.e( "TAG", Thread.currentThread().name + " 进度: " + read * 100 / total ) } .upload( RequestBodyBuilder() .addParam("a", "你好") .addFile(FileInfo("file", "1.jpg", file)) .addFile(FileInfo("file2", "2.jpg", file2)) .buildMultipartBody().parts ).exe() Log.e("TAG", executeExa.toString()) } ``` 文件下载,由于retrofit下载文件时,如果指定了Range,则会把文件下载到内存中,大文件容易造成oom,因此,文件下载功能是自己封装的AsyncTask,内部实现了断点下载、以及文件下载模式:COVER(覆盖原文件)、RENAME(文件名称冲突时,重命名)、IF_EXIT(如果下载路径有文件,则直接返回下载成功) ``` net.downloadFile("http://app.2345.cn/appsoft/81595.apk", getExternalFilesDir(null)?.absolutePath + "/kuake.apk", object : FileDownload { override fun cover(): Cover { return Cover.RENAME } override fun downloadStart() { Log.e("TAG", "开始下载") textView.text = "开始下载" } override fun downloadInProgress(writeBytes: Long, totalLength: Long) { textView.text = Thread.currentThread().name + " 进度: " + writeBytes * 100 / totalLength Log.e( "TAG", Thread.currentThread().name + " 进度: " + writeBytes * 100 / totalLength ) } override fun downloadSuccess(filePath: String) { Log.e("TAG", "下载完成:$filePath") textView.text = "下载完成:$filePath" } override fun downloadFail(errorMessage: String) { textView.text = "下载失败:$errorMessage" Log.e("TAG", "下载失败:$errorMessage") } override fun downloadCancel() { textView.text = "取消下载" } }).tag("aaa") //取消下载文件 net.canDownloadByTag("aaa") ``` 具体内容可见代码。 #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 码云特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)