Retrofit的基本post,get请求
2017-04-09 12:43
141 查看
一.简介
Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现。本文介绍的是Retrofit2.0+版本的使用
一个完整的Get请求
1.创建业务请求接口,具体代码如下:
获取北京天气的接口,get请求,参数是key和cityname,返回数据是WeatherDatapublic interface WeatherService{ @GET("weather/index") Call<WeatherData> getWeatherData(@Query("cityname") String cityname,@Query("key") String key); }
注:@GET注解就表示get请求,@Query表示请求参数,将会以key=value的方式拼接在url后面
Query非必填,如果请求参数非必填,可以传null,如果key非必填可以写成:
Call<WeatherData> call = service.getWeatherData("北京", null);
2.创建一个Retrofit的示例,并完成相应的配置
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://v.juhe.cn/") .addConverterFactory(GsonConverterFactory.create()) .build(); WeatherService service = retrofit.create(WeatherService.class);
这里的baseUrl就是网络请求URL相对固定的地址,一般包括请求协议(如Http)、域名或IP地址、端口号等,addConverterFactory方法表示需要用什么转换器来解析返回值,GsonConverterFactory.create()表示调用Gson库来解析json返回值。
3.调用请求方法,并得到Call实例
Call<WeatherData> call = service.getWeatherData("北京", "5c2dd6dd912ba8336889b0325689f809");
注:Call其实在Retrofit中就是行使网络请求并处理返回值的类
4.使用Call实例完成同步或异步请求
同步请求:WeatherData response = call.execute().body();
注:必须在子线程中执行,否则会报错
异步请求:
call.enqueue(new Callback<WeatherData>() { @Override public void onResponse(Call<WeatherData> call, Response<WeatherData> response) { mResault.setText(response.body().toString()); } @Override public void onFailure(Call<WeatherData> call, Throwable t) { Toast.makeText(MainActivity.this, "请求数据失败", Toast.LENGTH_SHORT).show(); } });
二.使用
首先需要在build.gradle文件中引入需要的第三包,配置如下:compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
Get请求
@QueryGet方法请求参数都会以key=value的方式拼接在url后面,Retrofit提供了两种方式设置请求参数。第一种就是像上文提到的直接在interface中添加@Query注解,还有一种方式是通过Interceptor实现。
public class CustomInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); HttpUrl httpUrl = request.url().newBuilder() .addQueryParameter("token", "tokenValue") .build(); request = request.newBuilder().url(httpUrl).build(); return chain.proceed(request); } }
addQueryParameter就是添加请求参数的具体代码,这种方式比较适用于所有的请求都需要添加的参数,一般现在的网络请求都会添加token作为用户标识,那么这种方式就比较适合。
创建完成自定义的Interceptor后,还需要在Retrofit创建client处完成添加
addInterceptor(new CustomInterceptor()) @QueryMap
如果Query参数比较多,那么可以通过@QueryMap方式将所有的参数集成在一个Map统一传递
public interface WeatherService { @GET("weather/index") Call<WeatherData> getWeatherData(@QueryMap Map<String, String> params); }
调用的时候将所有的参数集合在统一的map中即可
Map<String, String> params = new HashMap<>(); params.put("cityname", "北京"); params.put("key", "5c2dd6dd912ba8336889b0325689f809"); Call<WeatherData> call = service.getWeatherData(params);
Query集合
如果需要添加相同Key值,但是value却有多个的情况,一种方式是添加多个@Query参数,还有一种简便的方式是将所有的value放置在列表中,然后在同一个@Query下完成添加,实例代码如下:public interface WeatherService { @GET("weather/index") Call<WeatherData> getWeatherData(@Query("name") List<String> name); }
相当于
Map<String, String> params = new HashMap<>(); params.put("name", "北京"); params.put("name", "南京"); @Path
如果请求的相对地址也是需要调用方传递,那么可以使用@Path注解
@GET("weather/{name}") Call<WeatherData> getWeatherData(@Path("name") String name); Call<WeatherData> call = WeatherService.getWeatherData("北京");
注:@Path可以用于任何请求方式,包括Get、Post、Put、Delete等
Post请求
@Field
Post请求需要把请求参数放置在请求体中,而非拼接在url后面
public interface NewsDataService { @FormUrlEncoded @POST("news/list") Call<NewsData> getNewsData(@Field("key") String key); }
注:@FormUrlEncoded将会自动将请求
4000
参数的类型调整为application/x-www-form-urlencoded,假如key传递的参数为”435678”,那么最后得到的请求体就是
key=”435678”
@Field注解将每一个请求参数都存放至请求体中,还可以添加encoded参数,该参数为boolean型,具体的用法为
@Field(value = “key”, encoded = true) String key
encoded参数为true的话,key-value-pair将会被编码,即将中文和特殊字符进行编码转换
@FieldMap
假如有多个请求参数,这个时候就可以用FieldMap
@FormUrlEncoded @POST("news/list") Call<NewsData> getNewsData(@FieldMap Map<String, String> params); Map<String, String> params = new HashMap<>(); params.put("key", "32451"); params.put("name", "北京"); params.put("startindex", 1); params.put("endindex", 10); Call<NewsData> getNewsData(params); @Body
如果Post请求参数有多个,那么统一封装到类中应该会更好,这样维护起来会非常方便
@FormUrlEncoded @POST("news/list") Call<NewsData> getNewsData(@Body Entity entity); public class Entity { public String key; public String name; public int startindex; public int endindex; }
//get和set方法…..
Entity entity = new Entity(); entity.setKey("32451"); entity.setName("北京"); entity.setStartindex(1); entity.setEndindex(10); Call<NewsData> getNewsData(entity);
上传文件
单张图片上传并携带参数
public interface UploadFileService { @Multipart @POST("uploaad/file") Call<ResponseBody> uploadFile(@Part MultipartBody.Part photo, @Part("description") RequestBody description); }
上传代码
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(“http://192.168.1.62:8080/UploadFile/“)
.addConverterFactory(GsonConverterFactory.create())
.build();
UploadFileService service = retrofit.create(UploadFileService.class); //sd卡下imgs下的一张图片(拍照或者从相册中选择都可以获取到图片文件) File file = new File(Environment.getExternalStorageDirectory()+"/imgs", "demo.png"); //设置Content-Type:application/octet-stream RequestBody photoRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file); //设置Content-Disposition:form-data; name="photo"; filename="demo.png" MultipartBody.Part photo = MultipartBody.Part.createFormData("photo", file.getName(), photoRequestBody); //添加参数description,并且是文本类型 RequestBody description = RequestBody.create(MediaType.parse("text/plain"), "图片的描述"); Call<ResponseBody> mCall = service.uploadFile(photo, description); mCall.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Toast.makeText(MainActivity.this, "上传失败", Toast.LENGTH_SHORT).show(); } });
多张图片上传并携带参数
@Multipart @POST("uploaad/files") Call<ResponseBody> uploadfiles(@PartMap Map<String, RequestBody> images, @Part("description") RequestBody description)
上传代码
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://192.168.1.68:8080/") .addConverterFactory(GsonConverterFactory.create()) .build(); UploadFileService service = retrofit.create(UploadFileService.class); //sd卡下imgs下的两张图片(拍照或者从相册中选择都可以获取到图片文件) File file1= new File(Environment.getExternalStorageDirectory()+"/imgs", "demo1.png"); File file2 = new File(Environment.getExternalStorageDirectory()+"/imgs", "demo2.png"); RequestBody photoRequestBody1 = RequestBody.create(MediaType.parse("application/octet-stream"), file1); RequestBody photoRequestBody2 = RequestBody.create(MediaType.parse("application/octet-stream"), file2); RequestBody description = RequestBody.create(MediaType.parse("text/plain"), "图片的描述"); Map<String,RequestBody> images = new HashMap<String,RequestBody>(); //添加file1 images.put("images\"; filename=\""+file1.getName(), photoRequestBody1); //添加file2 images.put("images\"; filename=\""+file2.getName(), photoRequestBody2); //添加图片描述 images.put("description", description); Call<ResponseBody> call = service.uploadfiles(images, description); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { t.printStackTrace(); Toast.makeText(MainActivity.this, "上传失败", Toast.LENGTH_SHORT).show(); } });
三.添加自定义的Headers
静态方法可以添加多个
public interface WeatherService { @Headers({ "Accept: application/vnd.yourapi.v1.full+json", "User-Agent: zhoujian_retrofit"}) @GET("weather/index") Call<WeatherData> getWeatherData(@QueryMap Map<String, String> params); }
也可以通过Interceptor来定义静态请求头
public class CustomInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request request = original.newBuilder() .header("User-Agent", "zhoujian_retrofit") .header("Accept", "application/vnd.yourapi.v1.full+json") .method(original.method(), original.body()) .build(); return chain.proceed(request); } }
然后在OkHttp创建Client实例时,添加RequestInterceptor即可
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
.addInterceptor(new CustomInterceptor())
.addInterceptor(logging)
.connectTimeout(DEFAULT_TIMEOUT,
TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.build();
}
动态方法
@GET("weather/index") Call<WeatherData> getWeatherData(@Header("Accept") String Accept, @Header("User-Agent") String zhoujian_retrofit, @Query("cityname") String cityname, @Query("key") String key);
四.网络请求日志
Retrofit官方提供了一个很方便查看日志的Interceptor,你可以控制你需要的打印信息类型.首先需要在build.gradle文件中引入logging-interceptor
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
同上文提到的CustomInterceptor一样,添加到OkHttpClient创建处即可
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); private static OkHttpClient getClient(){ HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); return new OkHttpClient.Builder() .addInterceptor(logging) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .build(); }
HttpLoggingInterceptor提供了4中控制打印信息类型的等级,分别是NONE,BASIC,HEADERS,BODY
NONE:没有任何日志信息
BASIC:打印请求类型,URL,请求体大小,返回值状态以及返回值的大小
HEADERS:打印返回请求和返回值的头部信息,请求类型,URL以及返回值状态码
BODY:打印请求和返回值的头部和body信息
最常用的是BODY
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
TAG设置为okhttp
Log.i("okhttp","返回数据==="+mString);
相关文章推荐
- RestTemplate的两种请求GET和POST.不含摘要和基本认证
- Android HttpClient GET或者POST请求基本使用方法
- Retrofit 动态参数(Get、Post请求)
- Postman基本使用——get、post请求、断言、环境变量
- 利用Retrofit执行Post、Get请求,通俗易懂
- GET和POST两种基本请求方法的区别
- Retrofit的基本使用(Get请求)
- 详解Retrofit 动态参数(非固定参数、非必须参数)(Get、Post请求)
- AFNetworking框架的基本使用——GET、POST登录 、设置请求与响应的数据格式
- 利用Retrofit执行Post、Get请求,通俗易懂
- Retrofit简单封装使用--Post请求封装请求体、Get请求通过参数、map方式构建url
- 两行代码搞定发送 Retrofit GET/POST 请求
- [置顶] 策略模式(注解版)实现 retrofit 的get和post请求的公共参数(二)
- GET和POST两种基本请求方法的区别
- NSURLSession的GET和POST请求基本使用
- Android HttpClient GET或者POST请求基本使用方法
- GET和POST两种基本请求方法的区别(转)
- Retrofit的Get与Post请求
- Android HttpClient GET或者POST请求基本使用方法
- Retrofit2的get请求和post请求