增加离线地图下载流程
This commit is contained in:
53
app/src/main/java/com/navinfo/omqs/http/NetResult.kt
Normal file
53
app/src/main/java/com/navinfo/omqs/http/NetResult.kt
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.navinfo.omqs.http
|
||||
|
||||
/**
|
||||
* Created by Mayokun Adeniyi on 23/05/2020.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 网络返回封装
|
||||
*/
|
||||
|
||||
/**
|
||||
* 在类名之前使用sealed关键字将类声明为密封类。
|
||||
* 密封类仅在编译时限制类型集来确保类型安全的重要性。
|
||||
* 密封类隐式是一个无法实例化的抽象类。
|
||||
*/
|
||||
/**
|
||||
* 二:密封类所具有的特性和与别的类具有不同之处
|
||||
|
||||
①Sealed class(密封类) 是一个有特定数量子类的类,看上去和枚举有点类似,所不同的是,在枚举中,我们每个类型只有一个对象(实例);而在密封类中,同一个类可以拥有几个对象。
|
||||
|
||||
②Sealed class(密封类)的所有子类都必须与密封类在同一文件中
|
||||
|
||||
③Sealed class(密封类)的子类的子类可以定义在任何地方,并不需要和密封类定义在同一个文件中
|
||||
|
||||
④Sealed class(密封类)没有构造函数,不可以直接实例化,只能实例化内部的子类
|
||||
*/
|
||||
/**
|
||||
* 如何获取密封类里面的函数方法
|
||||
* 只能创建密封类子类对象 通过密封类的子类对象调用密封类里的函数方法
|
||||
*/
|
||||
sealed class NetResult<out R> {
|
||||
|
||||
data class Success<out T>(val data: T?) : NetResult<T>()
|
||||
data class Failure(val code: Int, val msg: String) : NetResult<Nothing>()
|
||||
data class Error(val exception: Exception) : NetResult<Nothing>()
|
||||
object Loading : NetResult<Nothing>()
|
||||
|
||||
/**
|
||||
* 密封类通常与表达when时一起使用。 由于密封类的子类将自身类型作为一种情况。
|
||||
因此,密封类中的when表达式涵盖所有情况,从而避免使用else子句。
|
||||
*/
|
||||
override fun toString(): String {
|
||||
return when (this) {
|
||||
is Success<*> -> "网络访问成功,返回正确结果Success[data=$data]"
|
||||
is Failure -> "网络访问成功,返回错误结果Failure[$msg]"
|
||||
is Error -> "网络访问出错 Error[exception=$exception]"
|
||||
is Loading -> "网络访问中 Loading"
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 密封类里面可以有若干个子类,这些子类如果要继承密封类,则必须和密封类在同一个文件里
|
||||
*/
|
||||
13
app/src/main/java/com/navinfo/omqs/http/NetworkService.kt
Normal file
13
app/src/main/java/com/navinfo/omqs/http/NetworkService.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.navinfo.omqs.http
|
||||
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
|
||||
/**
|
||||
* 网络访问 业务接口
|
||||
*/
|
||||
interface NetworkService {
|
||||
/**
|
||||
* 获取离线地图城市列表
|
||||
*/
|
||||
suspend fun getOfflineMapCityList():NetResult<List<OfflineMapCityBean>>
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.navinfo.omqs.http
|
||||
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 网络访问业务接口的具体实现
|
||||
*/
|
||||
class NetworkServiceImpl @Inject constructor(
|
||||
private val netApi: RetrofitNetworkServiceAPI,
|
||||
) : NetworkService {
|
||||
/**
|
||||
* 获取离线地图城市列表
|
||||
*/
|
||||
override suspend fun getOfflineMapCityList(): NetResult<List<OfflineMapCityBean>> =
|
||||
//在IO线程中运行
|
||||
withContext(Dispatchers.IO) {
|
||||
return@withContext try {
|
||||
val result = netApi.retrofitGetOfflineMapCityList()
|
||||
if (result.isSuccessful) {
|
||||
if (result.code() == 200) {
|
||||
NetResult.Success(result.body())
|
||||
} else {
|
||||
NetResult.Failure(result.code(), result.message())
|
||||
}
|
||||
} else {
|
||||
NetResult.Failure(result.code(), result.message())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
NetResult.Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package com.navinfo.omqs.http
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Streaming
|
||||
import retrofit2.http.Url
|
||||
import java.util.concurrent.Flow
|
||||
|
||||
/**
|
||||
* retrofit2 网络请求接口
|
||||
*/
|
||||
interface RetrofitNetworkServiceAPI {
|
||||
|
||||
/**
|
||||
* 在 Retrofit2 中,可以使用不同类型的返回值来获取 API 调用的结果。以下是 Retrofit2 支持的一些常见返回类型:
|
||||
|
||||
1. `Call<T>`:表示一个异步请求,其中 `T` 是 API 响应的类型,通常是一个自定义的数据类。使用 `enqueue` 方法来执行异步请求,并在回调中处理响应。
|
||||
|
||||
2. `Response<T>`:表示一个同步请求的响应,其中 `T` 是 API 响应的类型。使用 `execute` 方法来执行同步请求,并返回一个 `Response` 对象,其中包含了响应的状态码、响应头和响应体等信息。
|
||||
|
||||
3. `Observable<T>`:表示一个 RxJava 的 Observable 对象,其中 `T` 是 API 响应的类型。使用 `subscribe` 方法来执行请求,并在 onNext 回调中处理响应。
|
||||
|
||||
4. `Single<T>`:表示一个 RxJava 的 Single 对象,其中 `T` 是 API 响应的类型。使用 `subscribe` 方法来执行请求,并在 onSuccess 回调中处理响应。
|
||||
|
||||
5. `Completable`:表示一个 RxJava 的 Completable 对象,用于执行没有响应体的 API 调用。使用 `subscribe` 方法来执行请求,并在 onComplete 回调中处理响应。
|
||||
|
||||
6. `Flowable<T>`:表示一个 RxJava 的 Flowable 对象,其中 `T` 是 API 响应的类型。类似于 Observable,但支持背压处理。
|
||||
|
||||
7. `Deferred<T>`:表示一个 Kotlin 的 Deferred 对象,其中 `T` 是 API 响应的类型。使用 `await` 方法来执行请求,并返回响应的结果。
|
||||
|
||||
8. `LiveData<Response<T>>`:表示一个 LiveData 对象,其中 `T` 是 API 响应的类型。使用 `observe` 方法来执行请求,并在回调中处理响应。
|
||||
|
||||
总之,Retrofit2 支持多种返回类型,开发者可以根据项目需求选择合适的方式来处理 API 响应结果。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取离线地图城市列表
|
||||
*/
|
||||
@GET("/drdc/MapDownload/maplist")
|
||||
suspend fun retrofitGetOfflineMapCityList(): Response<List<OfflineMapCityBean>>
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*/
|
||||
@Streaming
|
||||
@GET
|
||||
suspend fun retrofitDownLoadFile(@Url url: String):Response<ResponseBody>
|
||||
|
||||
|
||||
/**
|
||||
* @FormUrlEncoded 请求格式注解,请求实体是一个From表单,每个键值对需要使用@Field注解
|
||||
@Field 请求参数注解,提交请求的表单字段,必须要添加,而且需要配合@FormUrlEncoded使用
|
||||
“token” 参数字段,与后台给的字段需要一致
|
||||
String 声明的参数类型
|
||||
token 实际参数,表示后面token的取值作为"token"的值
|
||||
Post请求如果有参数需要在头部添加@FormUrlEncoded注解,表示请求实体是一个From表单,每个键值对需要使用@Field注解,使用@Field添加参数,这是发送Post请求时,提交请求的表单字段,必须要添加的,而且需要配合@FormUrlEncoded使用,若为在头部添加@FormUrlEncoded注解,会抛出如下异常:
|
||||
当有多个不确定参数时,我们可以使用@FieldMap注解,@FieldMap与@Field的作用一致,可以用于添加多个不确定的参数,类似@QueryMap,Map的key作为表单的键,Map的value作为表单的值。
|
||||
*/
|
||||
// @FormUrlEncoded
|
||||
// @POST("api/dog")
|
||||
// fun postCall(@Field("token") token: String?): Call<Any?>?
|
||||
|
||||
/**
|
||||
* 当有多个不确定参数时,我们可以使用@FieldMap注解,@FieldMap与@Field的作用一致,可以用于添加多个不确定的参数,类似@QueryMap,Map的key作为表单的键,Map的value作为表单的值。
|
||||
*/
|
||||
// @FormUrlEncoded
|
||||
// @POST("api/dog")
|
||||
// open fun postCall(@FieldMap map: Map<String?, Any?>?): Call<Any?>?
|
||||
/**
|
||||
* @GET("v7/weather/now")
|
||||
Call<Wth_now_out> getCall(@QueryMap Map<String, Object> map);
|
||||
*/
|
||||
// @GET("v7/weather/now")
|
||||
// open fun getCall(@QueryMap map: Map<String?, Any?>?): Call<Wth_now_out?>?
|
||||
/**
|
||||
*@Query 请求参数注解,用于Get请求中的参数
|
||||
“location”/“key” 参数字段,与后台给的字段需要一致
|
||||
*/
|
||||
// @GET("v7/weather/now")
|
||||
// open fun getCall(@QueryMap map: Map<String?, Any?>?): Call<Wth_now_out?>?
|
||||
|
||||
/**
|
||||
* @FieldMap 请求参数注解,与@Field作用一致,用于不确定表单参数
|
||||
Map<String, Object> map 通过Map将不确定的参数传入,相当于多个Field参数
|
||||
适用于Post请求的还有一个注解@Body,@Body可以传递自定义类型数据给服务器,多用于post请求发送非表单数据,比如用传递Json格式数据,它可以注解很多东西,比如HashMap、实体类等,我们来看看它用法:
|
||||
特别注意:@Body注解不能用于表单或者支持文件上传的表单的编码,即不能与@FormUrlEncoded和@Multipart注解同时使用
|
||||
*/
|
||||
// @POST("")
|
||||
// open fun getPsotDataBody(@Body body: RequestBody?): Call<Any?>?
|
||||
|
||||
/**
|
||||
* @Path
|
||||
使用第一个get请求网址
|
||||
*/
|
||||
// @GET("v7/weather/{time}")
|
||||
// open fun getCall(@Path("time") time: String?,@QueryMap map: Map<String?, Any?>?): Call<Wth_now_out?>?
|
||||
|
||||
/**
|
||||
* @QueryMap get请求方法参数的注解,上面已经解释了,这里就不重复讲
|
||||
@Path 请求参数注解,用于Url中的占位符{},在网址中的参数
|
||||
@Path注解用于Url中的占位符{},在网址中的参数,如上面 @GET(“v7/weather/{time}”)的time,通过{}占位符来标记time,使用@Path注解传入time的值,注意有的Url既有占位符又有"?"后面的键值对,其实@Query和@Path两者是可以共用的。在发起请求时,{time}会被替换为方法中第二个参数的值time。
|
||||
*/
|
||||
// Map<String ,Object> map = new HashMap<>()Map<String ,Object> map = new HashMap<>();
|
||||
// map.put("location","101010100");
|
||||
// map.put("key","a5cf6ab782a14013b08fb92a57dd2f72");
|
||||
// Call<Wth_now_out> call = apiService.getCall("now",map);
|
||||
/**
|
||||
* 最终{time}会被替换为now,此时形成的牵绊部分Url为:https://devapi.qweather.com/v7/weather/now,剩余**?号**后面的Url由@Query传入。
|
||||
*/
|
||||
|
||||
/**
|
||||
* @HTTP
|
||||
@HTTP注解的作用是替换@GET、@POST、@PUT、@DELETE、@HEAD以及更多拓展功能
|
||||
如可通过此注解代替@POST注解实现post请求,如下:
|
||||
method 表示请求的方法,区分大小写,这里的值retrofit不会再做任何处理,必须要保证正确
|
||||
path 网络请求地址路径
|
||||
hasBody 是否有请求体,boolean类型
|
||||
除请求接口部分的方法有变,别的部分与正常使用@POST请求一致,另外需要注意在使用@HTTP注解实现post请求时,若含有请求体,那么对应的标识注解@FormUrlEncoded一定要加上,若为别的请求体,那么就添加与之对应的标识注解。
|
||||
@HTTP注解可以通过method字段灵活设置具体请求方法,通过path设置网络请求地址,用的比较少。使用方法与设置的请求方法种类一致。
|
||||
*/
|
||||
|
||||
// @FormUrlEncoded
|
||||
// @POST("api/dog")
|
||||
// Call<Object> postCall(@FieldMap Map<String,Object> map);
|
||||
//
|
||||
// @FormUrlEncoded
|
||||
// @HTTP(method = "POST",path = "api/dog", hasBody = true)
|
||||
// Call<Object> postCall1(@FieldMap Map<String,Object> map);
|
||||
/**
|
||||
* @Url
|
||||
如果需要重新地址接口地址,可以使用@Url,将地址以参数的形式传入即可。如果有@Url注解时,GET传入的Url必须省略。不然会抛出如下异常。
|
||||
*/
|
||||
//错误的
|
||||
// @FormUrlEncoded
|
||||
// @POST("api/dog")
|
||||
// open fun postCall(@Url url: String?, @FieldMap map: Map<String?, Any?>?): Call<Any?>?
|
||||
//正确的
|
||||
// @FormUrlEncoded
|
||||
// @POST
|
||||
// open fun postCall(@Url url: String?, @FieldMap map: Map<String?, Any?>?): Call<Any?>?
|
||||
|
||||
/**
|
||||
* @Streaming
|
||||
* @Streaming 表示响应体的数据用流的方式返回,使用于返回数据比较大,该注解在下载大文件时特别有用
|
||||
*/
|
||||
// @Streaming
|
||||
// @POST("gists/public")
|
||||
// open fun getStreamingBig(): Call<ResponseBody?>?
|
||||
|
||||
/**
|
||||
* @Multipart、@part、@PartMap
|
||||
* @Multipart 表示请求实体是一个支持文件上传的表单,需要配合@Part和@PartMap使用,适用于文件上传
|
||||
@Part 用于表单字段,适用于文件上传的情况,@Part支持三种类型:RequestBody、MultipartBody.Part、 任意类型
|
||||
@PartMap 用于多文件上传, 与@FieldMap和@QueryMap的使用类似
|
||||
*/
|
||||
// @Multipart
|
||||
// @POST("user/followers")
|
||||
// open fun getPartData(@Part("name") name: RequestBody?, @Part file: Part?): Call<ResponseBody?>?
|
||||
|
||||
/**
|
||||
* 代码使用逻辑:
|
||||
* 首先声明类型,通过MediaType实现类型的声明,此处使用的时文本类型,然后会根据该类型转化为RequestBody对象,此处使用的参数委RequestBody对象,相当于讲周润发以文本格式转换委RequestBody对象,最终上传时与name形成键值对。
|
||||
*/
|
||||
// //声明类型,这里是文字类型
|
||||
// MediaType textType = MediaType.parse("text/plain");
|
||||
// //根据声明的类型创建RequestBody,就是转化为RequestBody对象
|
||||
// RequestBody name = RequestBody.create(textType, "周润发");
|
||||
|
||||
////创建文件,这里演示图片上传
|
||||
// File file = new File("文件路径");
|
||||
// if (!file.exists()) {
|
||||
// file.mkdir();
|
||||
// }
|
||||
////将文件转化为RequestBody对象
|
||||
////需要在表单中进行文件上传时,就需要使用该格式:multipart/form-data
|
||||
// RequestBody imgBody = RequestBody.create(MediaType.parse("image/png"), file);
|
||||
////将文件转化为MultipartBody.Part
|
||||
////第一个参数:上传文件的key;第二个参数:文件名;第三个参数:RequestBody对象
|
||||
// MultipartBody.Part filePart = MultipartBody.Part.createFormData("key", file.getName(), imgBody);
|
||||
/**
|
||||
* 对于文件类型的上传,我们一般使用MultipartBody.Part类型上传,在上面讲两个参数设置好后,然后调用接口使用请求方法即可:
|
||||
* 此种格式属于文本与文件混合发送的格式。
|
||||
*/
|
||||
// var partDataCall: Call<ResponseBody?>? = retrofit.create(Api::class.java).getPartData(name, filePart)
|
||||
|
||||
/**
|
||||
* @PartMap的使用与@FieldMap和@QueryMap的使用类似,用于多文件上传,我们直接看代码:
|
||||
*/
|
||||
// @Multipart
|
||||
// @POST("user/followers")
|
||||
// open fun getPartMapData(@PartMap map: Map<String?, Part?>?): Call<ResponseBody?>?
|
||||
|
||||
// File file1 = new File("文件路径");
|
||||
// File file2 = new File("文件路径");
|
||||
// if (!file1.exists()) {
|
||||
// file1.mkdir();
|
||||
// }
|
||||
// if (!file2.exists()) {
|
||||
// file2.mkdir();
|
||||
// }
|
||||
// RequestBody requestBody1 = RequestBody.create(MediaType.parse("image/png"), file1);
|
||||
// RequestBody requestBody2 = RequestBody.create(MediaType.parse("image/png"), file2);
|
||||
// MultipartBody.Part filePart1 = MultipartBody.Part.createFormData("file1", file1.getName(), requestBody1);
|
||||
// MultipartBody.Part filePart2 = MultipartBody.Part.createFormData("file2", file2.getName(), requestBody2);
|
||||
//
|
||||
// Map<String,MultipartBody.Part> mapPart = new HashMap<>();
|
||||
// mapPart.put("file1",filePart1);
|
||||
// mapPart.put("file2",filePart2);
|
||||
|
||||
/**
|
||||
* 有关MediaType方法
|
||||
* 概述:MediaType,即是Internet Media Type,互联网媒体类型,也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。(也就是说MediaType在网络协议的消息头里面叫做Content-Type)它使用两部分的标识符来确定一个类型,是为了表明我们传的东西是什么类型。
|
||||
常见的媒体格式类型如下:
|
||||
text/html : HTML格式
|
||||
text/plain :纯文本格式
|
||||
text/xml : XML格式
|
||||
image/gif :gif图片格式
|
||||
image/jpeg :jpg图片格式
|
||||
image/png:png图片格式
|
||||
以application开头的媒体格式类型:
|
||||
application/xhtml+xml :XHTML格式
|
||||
application/xml :XML数据格式
|
||||
application/atom+xml :Atom XML聚合格式
|
||||
application/json :JSON数据格式
|
||||
application/pdf :pdf格式
|
||||
application/msword : Word文档格式
|
||||
application/octet-stream : 二进制流数据(如常见的文件下载、上传)
|
||||
application/x-www-form-urlencoded : 中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式
|
||||
另外一种常见的媒体格式是上传文件之时使用的:
|
||||
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user