Retrofit入门[简单使用方式介绍哦]
2017-12-26 16:04
519 查看
一直用OkHttp感觉也没什么毛病,空闲时间看看Retrofit怎么使用
本篇仅介绍最基本的Retrofit用法,如有错误请提出,我会虚心请教并改正,谢谢
开门见山贴代码
javabean数据类User如下
做个解释
上面的第三个上传json(或者有需求是上传xml的,这里没有成功实现,如有需要的同学联系我,然后我会尽快待补)
注意事项代码里都加注释了,再次说明几点
有@Part的地方基本都要加@Multipart
有@PartMap的地方最好加@JvmSuppressWildcards,否则会出错(注释有)
下载文件时Retrofit会将文件流整个读进内存,避免OOM需添加@Streaming
代码贴上
做个解释
在数据解析器方面,我觉得直接返回json串后自己使用gson或者fastjson解析,又清楚也不麻烦,不太喜欢在构造Retrofit实例的时候就固定了解析方式,当然如果为了方便项目需求需要加也没问题
步骤大致就是:创建Retrofit实例,然后通过接口定义的请求得到Api实例,通过这个实例得到对应的Call对象,最后进行具体的请求
Controller代码贴上
做个解释
服务器就基于SSM(SpringMVC+Spring+Mybatis)
新手学习中,本篇未涉及难点和概念部分,即看完能够在项目中使用
如有关于Retrofit和服务端的问题,请留下回复,一起交流
本篇仅介绍最基本的Retrofit用法,如有错误请提出,我会虚心请教并改正,谢谢
一、接口
想必有所了解的同学都知道Retrofit是基于接口来进行请求,如下开门见山贴代码
interface RetrofitApi { /* 1. 仅请求服务器数据 */ @GET(".") fun register(): Call<String> /* 2. 上传参数 */ @GET("hi/register") fun register(@QueryMap map: Map<String, String>): Call<String> /* 3. ???上传json[暂时处于僵硬状态...] */ @POST("postJson") fun postJson(@Body user: User): Call<String> /* 4. 上传单个文件 */ @Multipart @POST(".") fun uploadFile(@Part("description") description: RequestBody, @Part file: MultipartBody.Part): Call<String> /* 5. 上传多个文件 & 多个参数 */ @JvmSuppressWildcards // [IllegalArgumentException: Parameter type must not include a type variable or wildcard] @Multipart @POST(".") fun uploadFiles(@PartMap fileMap: Map<String, RequestBody>, @QueryMap map: Map<String, String>): Call<String> /* 6. 下载文件 */ @Streaming // 避免下载大文件被Retrofit整个读进内存 @GET("downloadFile") fun download(): Call<ResponseBody> }
javabean数据类User如下
data class User(val password: String, val username: String)
做个解释
上面的第三个上传json(或者有需求是上传xml的,这里没有成功实现,如有需要的同学联系我,然后我会尽快待补)
注意事项代码里都加注释了,再次说明几点
有@Part的地方基本都要加@Multipart
有@PartMap的地方最好加@JvmSuppressWildcards,否则会出错(注释有)
下载文件时Retrofit会将文件流整个读进内存,避免OOM需添加@Streaming
二、具体的请求
刚开始,多写几遍最基本的请求步骤,加强记忆,不急着封装啥的代码贴上
object RetrofitRequest { @JvmStatic fun main(args: Array<String>) { // register() // registerWithParams() // postJson() // uploadFile() // uploadFiles() download() } private fun register() { // 先来个模子 -> 给模子加花 -> 通过模子刻个实例出来 val retrofit = Retrofit.Builder() // 创建客户端建造器 .baseUrl("http://127.0.0.1:8080/hi/register/") // 添加主机地址 .addConverterFactory(ScalarsConverterFactory.create()) // 制定数据解析器[可用gson、jackson等或自定制] .build() // 创建客户端实例 val api = retrofit.create(RetrofitApi::class.java) // 获取Api实例 val call = api.register() // 通过Api实例获取一个Call对象 call.enqueue(object : Callback<String> { // 开始请求[enqueue(异步) | execute(同步)] override fun onFailure(call: Call<String>?, t: Throwable?) { println("请求失败: ${t.toString()}") } override fun onResponse(call: Call<String>?, response: Response<String>?) { println("请求成功: ${response?.body()}") } }) } private fun registerWithParams() { val retrofit = Retrofit.Builder() .baseUrl("http://127.0.0.1:8080/") .addConverterFactory(ScalarsConverterFactory.create()) .build() val api = retrofit.create(RetrofitApi::class.java) val call = api.register(mapOf("username" to "catface", "password" to "root")) // 添加请求参数map call.enqueue(object : Callback<String> { override fun onResponse(call: Call<String>?, response: Response<String>?) { println("请求成功: ${response?.body()}") } override fun onFailure(call: Call<String>?, t: Throwable?) { println("请求失败: ${t.toString()}") } }) } // 僵硬中... private fun postJson() { val retrofit = Retrofit.Builder() .baseUrl("http://127.0.0.1:8080/") .addConverterFactory(GsonConverterFactory.create()) .build() val api = retrofit.create(RetrofitApi::class.java) val call = api.postJson(User("root", "catface")) call.enqueue(object : Callback<String> { override fun onFailure(call: Call<String>?, t: Throwable?) { println("请求失败: ${t.toString()}") } override fun onResponse(call: Call<String>?, response: Response<String>?) { println("请求成功: ${response?.body()}") } }) } private fun uploadFile() { val retrofit = Retrofit.Builder() .addConverterFactory(ScalarsConverterFactory.create()) .baseUrl("http://127.0.0.1:8080/hi/uploadFileByJava/") .build() val api = retrofit.create(RetrofitApi::class.java) val file = File("D:/下载/图片/ic_launcher.png") val requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file) val fileBody = MultipartBody.Part.createFormData("file", file.name, requestBody) val description = RequestBody.create(MediaType.parse("multipart/form-data"), "This is a description") val call = api.uploadFile(description, fileBody) call.enqueue(object : Callback<String> { override fun onResponse(call: Call<String>, response: Response<String>) { println("请求成功: ${response.body().toString()}") } override fun onFailure(call: Call<String>, t: Throwable) { println("请求失败: ${t.toString()}") } }) } private fun uploadFiles() { val retrofit = Retrofit.Builder() .baseUrl("http://127.0.0.1:8080/hi/uploadFileBySpringAndFileName/") .addConverterFactory(ScalarsConverterFactory.create()) .build() val api = retrofit.create(RetrofitApi::class.java) /* 文件 */ val fileMap = HashMap<String, RequestBody>() val file1 = File("D:/下载/图片/ic_launcher.png") val file2 = File("D:/下载/图片/girl01.jpg") fileMap.put("file1\"; filename=\"" + file1.name, RequestBody.create(MediaType.parse("multipart/form-data"), file1)) fileMap.put("file2\"; filename=\"" + file2.name, RequestBody.create(MediaType.parse("multipart/form-data"), file2)) /* 参数 */ val map = HashMap<String, String>() map.put("username", "catface") map.put("password", "root") val call = api.uploadFiles(fileMap, map) call.enqueue(object : Callback<String> { override fun onResponse(call: Call<String>?, response: Response<String>?) { println("请求成功: ${response?.body()}") } override fun onFailure(call: Call<String>?, t: Throwable?) { println("请求失败: ${t.toString()}") } }) } private fun download() { val retrofit = Retrofit.Builder() .baseUrl("http://127.0.0.1:8080/hi/") .addConverterFactory(ScalarsConverterFactory.create()) .build() val api = retrofit.create(RetrofitApi::class.java) val call = api.download() call.enqueue(object : Callback<ResponseBody> { override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) { println("请求成功") if (response!!.isSuccessful) { writeResponseBodyToDisk(response.body()!!) } } override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) { println("请求失败: ${t.toString()}") } }) } /* 将流写到本地的工具 */ fun writeResponseBodyToDisk(body: ResponseBody): Boolean { try { val futureStudioIconFile = File("d:/a_test_dir/Future Studio Icon.jpg") var inputStream: InputStream? = null var outputStream: OutputStream? = null try { val fileReader = ByteArray(4096) val fileSize = body.contentLength() var fileSizeDownloaded: Long = 0 inputStream = body.byteStream() outputStream = FileOutputStream(futureStudioIconFile) while (true) { val read = inputStream!!.read(fileReader) if (read == -1) { break } outputStream.write(fileReader, 0, read) fileSizeDownloaded += read.toLong() println("file download: $fileSizeDownloaded of $fileSize") } outputStream.flush() return true } catch (e: IOException) { return false } finally { if (inputStream != null) { inputStream.close() } if (outputStream != null) { outputStream.close() } } } catch (e: IOException) { return false } } }
做个解释
在数据解析器方面,我觉得直接返回json串后自己使用gson或者fastjson解析,又清楚也不麻烦,不太喜欢在构造Retrofit实例的时候就固定了解析方式,当然如果为了方便项目需求需要加也没问题
步骤大致就是:创建Retrofit实例,然后通过接口定义的请求得到Api实例,通过这个实例得到对应的Call对象,最后进行具体的请求
三、服务端
为了方便同学们了解服务端是怎么接收文件和参数的,在此贴出我写的完整的服务端小demo,可做大家入门案例,灰常简单,且功能很全,能接收客户端传来的各种参数、文件,而且能返回给客户端字符串、json串、还能提供文件给客户端进行下载,直接看,不用害怕Controller代码贴上
@Controller @RequestMapping("hi") public class HiController { /******************************************** 与客户端进行入参出参联系 ********************************************/ /** * 1. 接收参数 --> 返回字符串 */ @RequestMapping(value = "/register", produces = "application/json; charset=utf-8") @ResponseBody public String register(HttpServletRequest request) { System.out.println("接口开始执行-->register"); Map<String, String[]> map = request.getParameterMap(); if (null == map || map.size() < 1) return "本次请求未上传任何参数"; String result = ""; for (String key : map.keySet()) { System.out.println(key + "-" + map.get(key)[0]); result += "\r\n" + key + "-" + map.get(key)[0]; } return result; } /** * 接收json串 */ @RequestMapping(value = "/postJson", method = RequestMethod.POST, produces = "application/json; charset=utf-8") @ResponseBody public String postJson(@RequestBody Map<String, String> map) throws IOException { System.out.println("接口开始执行-->postJson"); if (null == map || map.size() < 1) return "本次请求未上传任何参数"; String result = ""; for (String key : map.keySet()) { System.out.println(key + "-" + map.get(key)); result += "\r\n" + key + "-" + map.get(key); } return result; } /** * 2. 接收参数 --> 返回json */ @RequestMapping(value = "/login", produces = "application/json; charset=utf-8") @ResponseBody public String login(@RequestParam("username") String username, @RequestParam("password") String password) throws IOException { System.out.println("接口开始执行-->login"); /* 接收入参 */ System.out.println(username + " || " + password); /* 提供出参[json格式] */ Map<String, String> map = new HashMap<String, String>(); map.put("username", "测试中文 your username is: " + username); map.put("password", "测试中文 your password is: " + password); /* 返回json给客户端 */ return JSON.toJSONString(map); } @RequestMapping(value = "/receiveArr") public void receiveArr(@RequestParam("ids[]") String[] ids) { System.out.println("接口开始执行-->receiveArr"); for (String id : ids) { System.out.println(id); } } /******************************************** 客户端上传文件 ********************************************/ /** * ↓通过流保存上传的文件(耗时较长) * * @param file 将文件封装成CommonsMultipartFile */ @RequestMapping("/uploadFileByStream") @ResponseBody public String uploadFileByStream(@RequestParam("file") CommonsMultipartFile file) throws IOException { System.out.println("接口开始执行-->uploadFileByStream"); OutputStream os = new FileOutputStream("d:/" + file.getOriginalFilename()); InputStream is = file.getInputStream(); int temp; while ((temp = is.read()) != -1) { os.write(temp); } os.flush(); os.close(); is.close(); return "uploadFileByStream suc..."; } /** * ↓通过Java API: file.transferTo()保存上传的单个文件 */ @RequestMapping("/uploadFileByJava") @ResponseBody public String uploadFileByJava(@RequestParam("file") CommonsMultipartFile file) throws IOException { System.out.println("接口开始执行-->uploadFileByJava"); file.transferTo(new File("d:/" + file.getOriginalFilename())); return "uploadFileByJava suc... "; } /** * ↓通过Spring API保存上传的多个文件 */ @RequestMapping("/uploadFilesBySpring") @ResponseBody public String uploadFilesBySpring(HttpServletRequest request) throws IOException { System.out.println("接口开始执行-->uploadFilesBySpring"); String desPath; CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); if (multipartResolver.isMultipart(request)) { MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; Iterator<String> iterator = multiRequest.getFileNames(); while (iterator.hasNext()) { MultipartFile file = multiRequest.getFile(iterator.next()); if (null != file) { desPath = "d:/tt/" + file.getOriginalFilename(); file.transferTo(new File(desPath)); } } } return "uploadFilesBySpring suc..."; } /** * →接收文件map & 请求参数map← */ @RequestMapping(value = "/uploadFileBySpringAndFileName", method = RequestMethod.POST, produces = "application/json; charset=utf-8") @ResponseBody public String uploadFileBySpringAndFileName(HttpServletRequest request) throws IOException { System.out.println("接口开始执行-->uploadFileBySpringAndFileName"); /* 1. 获取所有参数 */ Map<String, String[]> parameterMap = request.getParameterMap(); System.out.println("参数数量: " + parameterMap.size()); // 入参数量 for (String key : parameterMap.keySet()) { System.out.println(key + ":" + parameterMap.get(key)[0]); } /* 2. 获取所有文件 */ CommonsMultipartResolver multiResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); if (multiResolver.isMultipart(request)) { MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; MultiValueMap<String, MultipartFile> multiFileMap = multiRequest.getMultiFileMap(); System.out.println("文件数量: " + multiFileMap.size()); // 入参数量 for (String key : multiFileMap.keySet()) { System.out.println(key + " : " + multiFileMap.get(key).get(0).getOriginalFilename()); multiFileMap.get(key).get(0).transferTo(new File("d:/a_test_dir/" + multiFileMap.get(key).get(0).getOriginalFilename())); } /*Iterator<String> iterator = multiRequest.getFileNames(); while (iterator.hasNext()) { Map<String, MultipartFile> fileMap = multiRequest.getFileMap(); MultipartFile file = fileMap.get("file"); System.out.println(file.getOriginalFilename()); }*/ } return "uploadFileBySpringAndFileName suc..."; } /* 添加一个网上的小demo,没啥用,随便看看 */ @RequestMapping("/uploadFiles") @ResponseBody public String uploadFiles(HttpServletRequest request) throws IOException { System.out.println("接口开始执行-->uploadFiles"); //创建一个通用的多部分解析器 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); //判断 request 是否有文件上传,即多部分请求 if (multipartResolver.isMultipart(request)) { //转换成多部分request MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; //取得request中的所有文件名 Iterator<String> iter = multiRequest.getFileNames(); while (iter.hasNext()) { //记录上传过程起始时的时间,用来计算上传时间 int pre = (int) System.currentTimeMillis(); //取得上传文件 MultipartFile file = multiRequest.getFile(iter.next()); if (file != null) { //取得当前上传文件的文件名称 String myFileName = file.getOriginalFilename(); //如果名称不"",说明该文件存在,否则说明该文件不存在 if (myFileName.trim() != "") { System.out.println(myFileName); //重命名上传后的文件名 String fileName = "demoUpload" + file.getOriginalFilename(); //定义上传路径 String path = "D:/a_test_dir/" + fileName; File localFile = new File(path); file.transferTo(localFile); } } //记录上传该文件后的时间 int finaltime = (int) System.currentTimeMillis(); System.out.println(finaltime - pre); } } return "/success"; } /******************************************* 向页面输出验证码png ********************************************/ @RequestMapping("/verificationCode") public void verificationCode(HttpServletResponse response, HttpSession session) throws IOException { System.out.println("接口开始执行-->verificationCode"); Object[] objs = ImageUtil.createImage(); session.setAttribute("imgCode", objs[0]); BufferedImage img = (BufferedImage) objs[1]; response.setContentType("image/png"); OutputStream os = response.getOutputStream(); ImageIO.write(img, "png", os); } /******************************************* 向客户端提供文件下载 ********************************************/ @RequestMapping("/downloadFile") public ResponseEntity<byte[]> downloadFile() throws IOException { System.out.println("接口开始执行-->downloadFile"); File file = new File("C:\\Users\\Administrator\\Desktop\\temp.jpg"); HttpHeaders headers = new HttpHeaders(); headers.setContentDispositionFormData("attachment", "temp.jpg"); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentLength(file.length()); System.out.println(file.length() + " is length,.."); return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED); } }
做个解释
服务器就基于SSM(SpringMVC+Spring+Mybatis)
新手学习中,本篇未涉及难点和概念部分,即看完能够在项目中使用
如有关于Retrofit和服务端的问题,请留下回复,一起交流
相关文章推荐
- Retrofit基本介绍和简单的使用方式
- android 介绍Retrofit的简单使用
- SpringSecurity 3.2入门(6)简单介绍默认使用的十一个过滤器
- Retrofit的简单介绍使用
- 【Retrofit】简单介绍和使用
- android 介绍Retrofit的简单使用
- Retrofit简单介绍和使用
- Retrofit简单入门及使用
- binbinyang-- Retrofit 2.0的简单使用(入门篇)-GET请求
- Retrofit的使用,及介绍,Retrofit中的各种方法的详细描述简单案例,三分钟学会Retrofit
- Java -- POI -- 入门使用以及简单介绍
- MongoDB工具MagicMongoDBTool使用介绍(一) -- 简单MongoDB入门
- [Android]RxJava的简单介绍和基本使用(二):retrofit2的简单介绍
- 网站前端_EasyUI.基础入门.0001.jQuery EasyUI简单介绍与快速使用?
- android 介绍Retrofit的简单使用
- 【Facebook的UI开发框架React入门之八】Image的使用简单介绍(iOS平台)-goodmao
- Retrofit2的使用简单介绍
- Android Retrofit的简单介绍和使用
- WebService介绍与简单使用(CXF方式)
- 简单入门使用Retrofit+ rxjava 下载图片