Android Retrofit 2.0使用

转:http://wuxiaolong.me/2016/01/15/retrofit/

添加依赖

app/build.gradle

compile 'com.squareup.retrofit2:retrofit:2.1.0'
创建API接口

  在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)

@GET("saveUser")
    Call<ResponseBody> saveUserByQuery(@Query("username") String username,
                                       @Query("age") int age,
                                       @Query("nickname") String nickname);
@QueryMap
@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
//加载天气
    @GET("adat/sk/{cityId}.html")
    Call<ResponseBody> getWeather(@Path("cityId") String cityId);
@Path 会将{}中的数据替换成@path参数的值

@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

依赖以下:

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'io.reactivex:rxandroid:1.2.1'
增加addCallAdapterFactory

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.weather.com.cn/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

接口
@GET("adat/sk/{cityId}.html")
    Observable<WeatherJson> getWeatherRxjava(@Path("cityId") String cityId);
subscribe部分的代码在Schedulers.io被调用,需要把observeOn(AndroidSchedulers.mainThread())添加到链表中

 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


















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android使用 Retrofit 上传图片可以通过 `@Multipart` 和 `@Part` 注解实现。以下是 Retrofit 2.0 实现图文上传的方法总结: 1. 添加依赖库 在项目的 `build.gradle` 文件中添加以下依赖库: ```groovy implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' ``` 2. 创建 Retrofit 实例 ```java Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); ``` 3. 创建 API 接口 ```java public interface ApiService { @Multipart @POST("upload") Call<ResponseBody> upload( @Part("description") RequestBody description, @Part MultipartBody.Part file); } ``` 其中,`@Multipart` 注解表示这是一个包含文本和文件的表单;`@POST("upload")` 表示上传的 URL 地址;`@Part("description") RequestBody description` 表示上传的文本参数,`description` 是参数名,可以自己定义;`@Part MultipartBody.Part file` 表示上传的文件参数。 4. 创建请求参数 ```java File file = new File(filePath); RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file); MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile); RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), "description"); ``` 5. 发送网络请求 ```java ApiService apiService = retrofit.create(ApiService.class); Call<ResponseBody> call = apiService.upload(description, body); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { // 成功上传后的处理 } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 上传失败后的处理 } }); ``` 以上就是 Retrofit 2.0 实现图文上传的方法总结。注意,在 `AndroidManifest.xml` 文件中需要添加网络权限: ```xml <uses-permission android:name="android.permission.INTERNET" /> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值