转:http://wuxiaolong.me/2016/01/15/retrofit/
添加依赖
app/build.gradle
创建API接口compile 'com.squareup.retrofit2:retrofit:2.1.0'
在retrofit中通过一个Java接口作为http请求的api接口。
/** * Call<T> get();必须是这种形式,这是2.0之后的新形式 * 如果不需要转换成Json数据,可以用ResponseBody * 你也可以使用Call<GsonBean> get();这样的话,需要添加Gson转换器*/ public interface ApiStores { //加载天气 @GET("adat/sk/{cityId}.html") Call<ResponseBody> getWeather(@Path("cityId") String cityId); }
接口调用
Retrofit retrofit = new Retrofit.Builder() //这里建议:-Base URL:总是以/结尾;-@Url:不要以/开头 .baseUrl(ApiStores.API_SERVER_URL) .build(); ApiStores apiStores = retrofit.create(ApiStores.class); apiStores.getWeather("101010100");
如果@GET(“http://ip.taobao.com/service/getIpInfo.php"),则baseUrl无效。
注意这个任务是网络任务,不要忘记给程序加入网络权限<uses-permission android:name="android.permission.INTERNET" />
同步调用
try { Response<ResponseBody> bodyResponse = call.execute(); String body = bodyResponse.body().string();//获取返回体的字符串 Log.i("wxl", "body=" + body); } catch (IOException e) { e.printStackTrace(); }
同步需要处理android.os.NetworkOnMainThreadException异步调用
call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Response<ResponseBody> response) { try { Log.i("wxl", "response=" + response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Throwable t) { Log.i("wxl", "onFailure=" + t.getMessage()); } });
移除请求
call.cancel();
get请求
@Query
如果链接是http://ip.taobao.com/service/getIpInfo.php?ip=202.202.33.33@GET("http://ip.taobao.com/service/getIpInfo.php") Call<ResponseBody> getWeather(@Query("ip") String ip)
@QueryMap@GET("saveUser") Call<ResponseBody> saveUserByQuery(@Query("username") String username, @Query("age") int age, @Query("nickname") String nickname);
调用@GET("saveUser") Call<ResponseBody> saveUserByQueryMap( @QueryMap Map<String, Object> options);
HashMap<String, Object> options = new HashMap<>(); options.put("username","xiaoming"); options.put("age",24); options.put("nickname","mingming"); Call<ResponseBody> call = apiStores.saveUserByQueryMap(options);
@Query和@QueryMap也可以结合在一起使用。
要是对应的url在服务端支持get/post两种类型的请求的话,@Query和@QueryMap@GET变为@POST也可以执行,
只不过post请求时所带的参数也会像get方式一样已?key=value&key1=vaule2…的形式拼接在url的后边post请求@Field 和 @FieldMap@FormUrlEncoded @POST("saveUser") Call<ResponseBody> saveUserByField( @Field("username") String username, @Field("age") int age, @Field("nickname") String nickname); @FormUrlEncoded @POST("saveUser") Call<ResponseBody> saveUserByFieldMap( @FieldMap Map<String, Object> options);
@Field和@FieldMap可以结合在一起使用。
另外是不是发现了比起@GET多了一个@FromUrlEncoded的注解。如果去掉@FromUrlEncoded在post请求中使用@Field和@FieldMap,
那么程序会抛出java.lang.IllegalArgumentException: @Field parameters can only be used with form encoding. (parameter #1)
的错误异常。
如果将@FromUrlEncoded添加在@GET上面呢,同样的也会抛出java.lang.IllegalArgumentException:FormUrlEncoded can only be specified on HTTP methods with request body (e.g., @POST).
的错误异常
@Path@Path 会将{}中的数据替换成@path参数的值//加载天气 @GET("adat/sk/{cityId}.html") Call<ResponseBody> getWeather(@Path("cityId") String cityId);
@Url 动态url可以看到,在public interface UserService { @GET public Call<ResponseBody> profilePicture(@Url String url); }
GET
上不需要结点url,我们可以直接在方法中去添加这个url
动态url:http://www.jianshu.com/p/4268e434150a请求体
可以通过
@Body
注解指定一个对象作为Http请求的请求体该对象将会被@POST("users/new") Call<User> createUser(@Body User user);
Retroofit
实例指定的转换器转换,如果没有添加转换器,则只有RequestBody
可用
使用OkHttp拦截器可以指定需要的header给每一个Http请求OkHttpClient client = new OkHttpClient(); client.networkInterceptors().add(new Interceptor() { @Override public com.squareup.okhttp.Response intercept(Chain chain) throws IOException { com.squareup.okhttp.Response response = chain.proceed(chain.request()); // Do anything with response here return response; } }); Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) ... .client(client) .build()
转换器
默认情况下,Retrofit只能够反序列化Http体为OkHttp的
ResponseBody
类型,并且只能够接受ResponseBody
类型的参数作为@body
。
添加转换器可以支持其他的类型,为了方便的适应流行的序列化库,Retrofit提供了六个兄弟模块:
- Gson : com.squareup.retrofit:converter-gson
- Jackson: com.squareup.retrofit:converter-jackson
- Moshi: com.squareup.retrofit:converter-moshi
- Protobuf: com.squareup.retrofit:converter-protobuf
- Wire: com.squareup.retrofit:converter-wire
- Simple XML: com.squareup.retrofit:converter-simplexml
添加gson依赖
app/build.gradle
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
Gsonformat
作用:Android studio插件,一般接口返回数据后要建立自己的bean,Gsonformat帮助你快速生成,不用一条一条去写。比jsonschema2pojo更加简单。
安装步骤:Android studio-Settings-Plugins-搜Gsonformat-Install Plugin
效果预览:
实例代码
依旧演示上面的天气:http://www.weather.com.cn/adat/sk/101010100.html
public class WeatherJson {
///* {"weatherinfo":{"city":"鍖椾含","cityid":"101010100","temp":"10","WD":"涓滃崡椋�","WS":"2绾�","SD":"26%","WSE":"2","time":"10:25","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB","njd":"鏆傛棤瀹炲喌","qy":"1012"}}*/
//weatherinfo需要对应json数据的名称,我之前随便写了个,被坑很久
private WeatherinfoBean weatherinfo;
public WeatherinfoBean getWeatherinfo() {
return weatherinfo;
}
public void setWeatherinfo(WeatherinfoBean weatherinfo) {
this.weatherinfo = weatherinfo;
}
public static class WeatherinfoBean {
private String city;
private String cityid;
private String temp;
private String WD;
private String WS;
private String SD;
private String WSE;
private String time;
private String isRadar;
private String Radar;
private String njd;
private String qy;
....
}
}
}
ApiStores:public class AppClient {
static Retrofit mRetrofit;
public static Retrofit retrofit() {
if (mRetrofit == null) {
mRetrofit = new Retrofit.Builder()
.baseUrl("http://www.weather.com.cn/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return mRetrofit;
}
public interface ApiStores {
@GET("adat/sk/{cityId}.html")
Call<WeatherJson> getWeather(@Path("cityId") String cityId);
}
}
调用:private void getWeather() {
AppClient.ApiStores apiStores = AppClient.retrofit().create(AppClient.ApiStores.class);
Call<WeatherJson> call = apiStores.getWeather("101010100");
call.enqueue(new Callback<WeatherJson>() {
@Override
public void onResponse(Response<WeatherJson> response) {
Log.i("wxl", "getWeatherinfo=" + response.body().getWeatherinfo().getCity());
}
@Override
public void onFailure(Throwable t) {
}
});
}
经Gson转换器,Call<ResponseBody>
换成自己要写的Call<WeatherJson>
提交Json格式数据
1.
<span style="font-size:12px;">@Headers({"Content-type:application/json;charset=UTF-8"})
@POST("testJson")
Call<ResponseBody> saveUserJson(@Body RequestBody route);</span>
调用<span style="font-size:12px;"> mRetrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.6:8787/Retrofit/")
// .addConverterFactory(GsonConverterFactory.create())
.build();
User user = new User();
user.setUsername("xiaoming");
user.setAge(25);
user.setNickname("jjk");
Gson gson=new Gson();
String route= gson.toJson(user);//通过Gson将Bean转化为Json字符串形式
ApiStores apiStores = mRetrofit.create(ApiStores.class);
RequestBody body=RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),route);
Call<ResponseBody> call = apiStores.saveUserJson(body);</span>
2.使用com.squareup.retrofit:converter-gson转换器
@POST("testJson")
Call<ResponseBody> saveUserJson(@Body User user);
调用 mRetrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.6:8787/Retrofit/")
.addConverterFactory(GsonConverterFactory.create())
.build();
User user = new User();
user.setUsername("xiaoming");
user.setAge(28);
user.setNickname("jjc");
ApiStores apiStores = mRetrofit.create(ApiStores.class);
Call<ResponseBody> call = apiStores.saveUserJson(user);
上传文件
@Multipart
@POST("uploadPic")
Call<ResponseBody> upload(@Part("desciption") RequestBody description, @Part MultipartBody.Part file);
调用<span style="font-size:12px;">mRetrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.6:8787/Retrofit/")
.build();
File file = new File(Environment.getExternalStorageDirectory(), "12.png");
// 创建 RequestBody,用于封装 请求RequestBody
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
//file:与服务器对应的key,fiele.getNmae()是服务器得到的文件名
// 添加描述
String descriptionString = "hello, 这是文件描述";
RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString);
FileUploadService service = mRetrofit.create(FileUploadService.class);
Call<ResponseBody> call = service.upload(description, body);</span>
上传一张图片@Multipart
@POST("uploadPic")
Call<ResponseBody> uploadImage(@Part("desciption") RequestBody desciption,
@Part("file\";filename=\"image.png") RequestBody requestBody);
"file\";filename=\"image.png" file是服务器上传对应的字段名,filename上传到服务器的文件名为image.png调用
<span style="font-size:12px;">mRetrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.6:8787/Retrofit/")
.build();
File file = new File(Environment.getExternalStorageDirectory(), "144.png");
//用RequestBody包裹文件,application/octet-stream为文件类型,这里为二进制流,不知道文件类型时所用
RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
FileUploadService apiService = mRetrofit.create(FileUploadService.class);
Call<ResponseBody> call = apiService.uploadImage(RequestBody.create(null, "hello,我是文件描述"), requestBody);</span>
上传多张图片
<span style="font-size:12px;">@Multipart
@POST("filesUpload")
Call<ResponseBody> uploadImages(@Part("desciption") RequestBody desciption,
@Part("files\";filename=\"image1.png") RequestBody img,
@Part("files\";filename=\"image2.png") RequestBody img2,
@Part("files\";filename=\"image3.png") RequestBody img3);</span>
调用<span style="font-size:12px;">mRetrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.6:8787/Retrofit/")
.build();
File file = new File(Environment.getExternalStorageDirectory(), "144.png");
File file2 = new File(Environment.getExternalStorageDirectory(), "145.png");
File file3 = new File(Environment.getExternalStorageDirectory(), "146.png");
//用RequestBody包裹文件,application/octet-stream为文件类型,这里为二进制流,不知道文件类型时所用
RequestBody img1 = RequestBody.create(MediaType.parse("application/octet-stream"), file);
RequestBody img2 = RequestBody.create(MediaType.parse("application/octet-stream"), file2);
RequestBody img3 = RequestBody.create(MediaType.parse("application/octet-stream"), file3);
FileUploadService service = mRetrofit.create(FileUploadService.class);
Call<ResponseBody> call = service.uploadImages(RequestBody.create(null, "哈哈,hello"), img1, img2, img3);</span>
使用
@PartMap调用<span style="font-size:12px;">@Multipart @POST("filesUpload") Call<ResponseBody> uploadImages2(@Part("desciption") RequestBody desciption, @PartMap Map<String, RequestBody> params); </span>
<span style="font-size:12px;">mRetrofit = new Retrofit.Builder() .baseUrl("http://192.168.1.6:8787/Retrofit/") .build(); File file = new File(Environment.getExternalStorageDirectory(), "144.png"); File file2 = new File(Environment.getExternalStorageDirectory(), "145.png"); File file3 = new File(Environment.getExternalStorageDirectory(), "146.png"); //用RequestBody包裹文件,application/octet-stream为文件类型,这里为二进制流,不知道文件类型时所用 RequestBody img1 = RequestBody.create(MediaType.parse("application/octet-stream"), file); RequestBody img2 = RequestBody.create(MediaType.parse("application/octet-stream"), file2); RequestBody img3 = RequestBody.create(MediaType.parse("application/octet-stream"), file3); FileUploadService apiService = mRetrofit.create(FileUploadService.class); Map<String, RequestBody> map = new HashMap<>(); map.put("files\";filename=\"144.png",img1); map.put("files\";filename=\"145.png",img2); map.put("files\";filename=\"146.png",img3); map.put("username", RequestBody.create(null, "abc"));//username 对应服务器的字段,上传字段的值为"abc" Call<ResponseBody> call = apiService.uploadImages2(RequestBody.create(null,"我是图片描述"), map); </span>
RxJava
依赖以下:
增加addCallAdapterFactorycompile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'io.reactivex:rxandroid:1.2.1'
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://www.weather.com.cn/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();
接口subscribe部分的代码在Schedulers.io被调用,需要把observeOn(AndroidSchedulers.mainThread())添加到链表中@GET("adat/sk/{cityId}.html") Observable<WeatherJson> getWeatherRxjava(@Path("cityId") String cityId);
ApiService apiService = retrofit.create(ApiService.class); Observable<WeatherJson> observable = apiService.getWeatherRxjava("101010100"); observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<WeatherJson>() { @Override public void onCompleted() { Log.e("xxxxx-", "onCompleted"); } @Override public void onError(Throwable e) { } @Override public void onNext(WeatherJson weatherJson) { Log.e("xxxxx", "onNext: " + weatherJson); } });
http://wuxiaolong.me/2016/01/15/retrofit/
http://blog.csdn.net/lmj623565791/article/details/51304204
https://my.oschina.net/kooeasy/blog/479773
http://blog.csdn.net/ljd2038/article/details/51046512