retrofit 2.0 简单使用

Retrofit与okhttp都是出于Square公司,Retrofit对okhttp做了一层包装,把网络请求都交给了okhttp(可以参考okhttp3使用),因此只需要简单的配置,就能用Retrofit进行网络请求。

一、引入retrofit 2.0

需要在项目下的build.gradle添加retrofit 2.0.2的引用

// retrofit 库
compile 'com.squareup.retrofit2:retrofit:2.0.2'
// 使用gson解析数据内容
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

这里写图片描述

如上图所示,引入retrofit 2.0.2后,会在External Libraries中看到retrofit-2.0.2okhttp-3.2.0okio-1.6.0,这是因为retrofit 2.0.2封装了okhttp-3.2.0,而okhttp-3.2.0又依赖于okio-1.6.0,因此引入一个retrofit库,会自动添加其依赖的其他库。

二、retrofit 2.0 基本使用

1、retrofit对象创建
Retrofit retrofit = new Retrofit.Builder()
                                // 设置基本url,通常是协议+IP地址+端口
                                .baseUrl(API_URL)
                                // 设置数据解析的格式,需要引入gson库 
                                .addConverterFactory(GsonConverterFactory.create())
                                .build();
2、retrofit网络请求接口

retrofit将Http Api使用Java接口表示;

public interface GitHub {
    @GET("/repos/{owner}/{repo}/contributors")
    Call<List<Contributor>> contributors(
            @Path("owner") String owner,
            @Path("repo") String repo);
}

每一个Call对象从GitHub接口里的方法获取,Call基于Http的同步/异步方法想服务端获取请求结果。

Call<List<Contributor>> call = github.contributors("square", "retrofit");
3、动态设置url的Get方法

retrofit 2.0允许动态设置 URL,需要使用一对大括号{}将需要动态替换的URL内容括起来,对应的参数使用相同的字符串,同时使用@Path注解表示。

如,需要请求这个地址(https://api.github.com/repos/square/retrofit/contributors)的数据,可以添加请求接口:

public interface GitHub {
    @GET("/repos/{owner}/{repo}/contributors")
    Call<List<Contributor>> contributors(
            @Path("owner") String owner,
            @Path("repo") String repo);
}

在实际调用的时候,传入正确的参数便可

Call<List<Contributor>> call = github.contributors("square", "retrofit");

这里给出完整的动态设置Url的同步调用Get方法源码;

/**
 * 同步方法
 */
private void btn_synchronous_dynamically_getMethod() {
    try {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // Create a very simple REST adapter which points the GitHub API.
                    Retrofit retrofit = new Retrofit.Builder()
                            // 设置基本url,通常是协议+IP地址+端口
                            .baseUrl(API_URL)
                            // 设置数据解析的格式,需要引入gson库
                            .addConverterFactory(GsonConverterFactory.create())
                            .build();

                    // Create an instance of our GitHub API interface.
                    GitHub github = retrofit.create(GitHub.class);

                    // Create a call instance for looking up Retrofit contributors.
                    Call<List<Contributor>> call = github.contributors("square", "retrofit");

                    // Fetch and print a list of the contributors to the library.
                    List<Contributor> contributors = call.execute().body();
                    final StringBuilder sb = new StringBuilder();
                    for (Contributor contributor : contributors) {
                        sb.append(contributor.getLogin() + " (" + contributor
                                .getContributions() + ")\n");
                    }
                    Log.i(TAG, "tht synchronous function run on thread id is " + Thread
                            .currentThread().getId());
                    Log.i(TAG, sb.toString());
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mToast.setText(sb.toString());
                            mToast.show();
                        }
                    });

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

注:Android 4.0之后,不允许网络请求在主线程中使用。

异步方法通过在Call的enqueue中添加结果回调来完成。如果需要获取Http原始的Response对象,使用Response raw = response.raw();

/**
 * 异步方法
 */
private void btn_asynchronous_dynamically_getMethod() {
    // Create a very simple REST adapter which points the GitHub API.
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(API_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    // Create an instance of our GitHub API interface.
    GitHub github = retrofit.create(GitHub.class);

    // Create a call instance for looking up Retrofit contributors.
    Call<List<Contributor>> call = github.contributors("square", "retrofit");

    // Fetch and print a list of the contributors to the library.
    call.enqueue(new Callback<List<Contributor>>() {
        @Override
        public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>>
                response) {
            try {
                // get raw response
                // Response raw = response.raw();
                Log.i(TAG, "tht callback function run on thread id is " + Thread
                        .currentThread().getId());
                StringBuilder sb = new StringBuilder();
                List<Contributor> contributors = response.body();
                for (Contributor contributor : contributors) {
                    sb.append(contributor.getLogin() + " (" + contributor
                            .getContributions() + ")\n");
                }
                mToast.setText(sb.toString());
                mToast.show();
                Log.i(TAG, sb.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<List<Contributor>> call, Throwable t) {

        }
    });
}
4、retrofit 查询参数
4.1、一个参数查询

如果只有一个查询参数的Get/Post请求,可以使用Query注解;
比如针对链接(http://api.k780.com:88/?app=weather.future)请求,需要设置java请求接口为:

    @POST("/")
    Call<WeatherList> getWeatherForAQuery(@Query("app") String queryParams);

注:参数查询不能使用@POST(“/app={param}”),然后通过@Path注解动态传递数值。

4.2、多个参数查询

如果查询参数有多个,需要使用QueryMap注解,参数通过Map<String,String>对象传递。当然,也可以只使用Query注解,不过需要添加多个Query注解才行;

public interface YourInterface {
    @GET("your-url")
    Call<responsebody> postcode(@Query("op") String op, @Query("postcode") String postcode);
}

下面演示对天气Url(http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json)数据请求;

定义请求天气的Java接口,如果是用Get请求,需要将@POST改成@GET,需要用到的WeatherList对象,可以再文章的最后下载demo;

public interface WeatherApi {
    @POST("/")
    Call<WeatherList> getWeatherForQueryMap(@QueryMap Map<String,String> options);
}

注:注解括号内容不能为空,即使baseUrl写成http://api.k780.com:88/,注解也不能为 @POST(“”),否则运行出错。

最终调用方法;

private void btn_asynchronous_queryParamete_getMethod() {
    try {
        Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.k780.com:88/")
                .addConverterFactory(GsonConverterFactory.create()).build();

        Map<String, String> options = new HashMap<String, String>();
        options.put("app", "weather.future");
        options.put("weaid", "1");
        options.put("appkey", "10003");
        options.put("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4");
        options.put("format", "json");
        Call<WeatherList> result = retrofit.create(WeatherApi.class).getWeather2(options);
        result.enqueue(new Callback<WeatherList>() {
            @Override
            public void onResponse(Call<WeatherList> call, Response<WeatherList> response) {
                Log.i("MainActivity", new Gson().toJson(response.body()));
            }

            @Override
            public void onFailure(Call<WeatherList> call, Throwable t) {

            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}
4.3、同名的多个查询参数

有些情况下通过同名的多个参数请求,比如https://api.example.com/tasks?id=123&id=124&id=125 ,由于参数数据类型是一样的,可以通过List<>组合多个参数;

public interface TaskService {  
    @GET("/tasks")
    Call<List<Task>> getTask(@Query("id") List<Long> taskIds);
}
5、发送json参数

当请求参数是个JSON字符串,可以使用@Body注解一个对象,Retrofit可以将一个对象转化为JSON字符串;

定义一个对象;

public class Task {  
    private long id;
    private String text;

    public Task(long id, String text) {
        this.id = id;
        this.text = text;
    }
}

声明请求数据接口;

public interface TaskService {  
    @POST("/tasks")
    Call<Task> createTask(@Body Task task);
}

调用方法;

Task task = new Task(1, "my task title");  
Call<Task> call = taskService.createTask(task);  
call.enqueue(new Callback<Task>() {}); 

调用createTask方法,把task对象的属性转化为JSON形式,对应的task参数实际为

{
    "id": 1,
    "text": "my task title"
}
5、文件上传

retrofit的文件上传,需要使用@Multipart注解;

文件上传接口定义;

public interface FileUploadService {
    public static final String BASE_URL = "http://your.api/endpoint/base-url";

    @Multipart
    @POST("/upload")
    void upload(@Part("myfile") TypedFile file,
                @Part("description") String description,
                Callback<String> cb);
}

定义call对象模板;

public class ServiceGenerator {

    public static final String API_BASE_URL = "http://your.api-base.url";

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass) {
        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(serviceClass);
    }
}

实际调用;

FileUploadService service = ServiceGenerator.createService(FileUploadService.class, FileUploadService.BASE_URL);
TypedFile typedFile = new TypedFile("multipart/form-data", new File("path/to/your/file"));
String description = "hello, this is description speaking";

service.upload(typedFile, description, new Callback<String>() {
    @Override
    public void success(String s, Response response) {
        Log.e("Upload", "success");
    }

    @Override
    public void failure(RetrofitError error) {
        Log.e("Upload", "error");
    }
});

TypedFileRetrofit中定义,提供Filemime type两个参数,这里使用的mime type值为multipart/form-data

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值