让你一文搞懂Retrofit使用

0 官方参考链接

Retrofit官方地址
http://square.github.io/retrofit/

Retrofit github地址
https://github.com/square/retrofit

1 Retrofit入门

1.1 Retrofit实例创建

Retrofit类实现GitHubService接口

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();


注1: Retrofit2 的baseUlr 必须以 /(斜线) 结束,不然会抛出一个IllegalArgumentException,所以如果你看到别的教程没有以 / 结束,那么多半是直接从Retrofit 1.X 照搬过来的。

注2: 上面的 注1 应该描述为 baseUrl 中的路径(path)必须以 / 结束, 因为有些特殊情况可以不以/结尾(感谢@liujc 提出,81楼),比如 其实这个 URL https://www.baidu.com?key=value用来作为baseUrl其实是可行的,因为这个URL隐含的路径就是 /(斜线,代表根目录) ,而后面的?key=value在拼装请求时会被丢掉所以写上也没用。之所以 Retrofit 2 在文档上要求必须以 /(斜线) 结尾的要求想必是要消除歧义以及简化规则。

1.2 接口定义

Retrofit是一个针对Android和Java类型安全的HTTP Client,
Retrofit将 HTTP API转成java接口

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

这里是interface不是class,所以我们是无法直接调用该方法,我们需要用Retrofit创建一个BlogService的代理对象。

GitHubService service = retrofit.create(GitHubService.class);

GitHubService创建的Call可以向远端发起一个同步或者异步的Http请求.

1.3 接口调用

拿到代理对象后可进行接口调用, 可以有同步方式和异步方式两种

Call<List<Repo>> repos = service.listRepos("octocat");

同步方式调用

repos.execute()

异步方式调用

Call<ResponseBody> call = service.getBlog(2);
// 用法和OkHttp的call如出一辙,
// 不同的是如果是Android系统回调方法执行在主线程
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        try {
            System.out.println(response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        t.printStackTrace();
    }
});

打印结果:

{"code":200,"msg":"OK","data":{"id":2,"date":"2016-04-15 03:17:50","author":"怪盗kidou","title":"Retrofit2 测试2","content":"这里是 Retrofit2 Demo 测试服务器2"},"count":0,"page":0}

2 Retrofit注解详解

上面提到Retrofit 共22个注解,这节就专门介绍这22个注解,为帮助大家更好理解我将这22个注解分为三类,并用表格的形式展现出来,表格上说得并不完整,具体的见源码上的例子注释。

retrofit通过使用注解来简化请求,大体分为以下几类:

  1. 用于标注请求方式的注解
  2. 用于标记请求头的注解
  3. 用于标记请求参数的注解
  4. 用于标记请求和响应格式的注解

2.1 HTTP请求方法的注解

分类名称说明备注
请求方法GETget请求分别对应HTTP的请求方法
请求方法POSTpost请求都接收一个字符串表示接口
请求方法PUTput请求与baseUrl组成完整Url
请求方法DELETEdelete请求不过也可以不指定结合下面的@Url注解使用
请求方法PATCHpatch请求,该请求是对put请求的补充,用于更新局部资源url中也可以使用变量如{id}
请求方法HEADHeader请求并使用@Path(“id”)注解{id}提供值
请求方法OPTIONSoption请求
请求方法HTTP通过注解,可以替换以上所有的注解,其拥有三个属性:method, path, hasBody可以用于替换以上7个,以及其它扩展方法

表1 请求方法

以上表格中除了HTTP以外都对应了HTTP标准中的请求方法,而HTTP注解则可以代替以上方法中任意一个注解,有三个属性: method, path, hasBody, 下面是用HTTP注解实现的接口

public interface BlogService {
    /**
     * method 表示请求的方法,区分大小写
     * path表示路径
     * hasBody表示是否有请求体
     */
    @HTTP(method = "GET", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getBlog(@Path("id") int id);
}

注: method 的值 retrofit 不会做处理,所以要自行保证其准确性,之前使用小写也可以是因为示例源码中的服务器不区分大小写,所以希望大家注意,感谢 @言過祺實 发现该问题

2.2 请求头注解

注解说明
@Headers用于添加固定请求头,可以同时添加多个。通过该注解添加的请求头不会相互覆盖,而是共同存在
@Header作为方法的参数传入,用于添加不固定值的Header,该注解会更新已有的请求头

2.3 请求和响应格式注解

分类名称备注
表单请求@FormUrlEncoded表示请求发送编码Form表单数据,每个键值对需要使用@Field注解,你在网站上看到登录页面就是用这种请求方式Content-Type:application/x-www-form-urlencoded
表单请求@Multipart表示请求体是一个支持文件上传的Form表单,你看到带文件上传的网页就是用的这种请求方式Content-Type:multipart/form-data
标记Streaming表示响应体的数据用流的形式返回如果没有使用该注解,默认会把数据全部载入内存,之后你通过流获取数据也不过是读取内存中的数据所以如果你的返回数据比较大,你就需要使用这个注解

表2 标记类注解

2.4 请求参数注解

分类名称备注
*@Body多用于非表单请求体, 比如想要以post方式传递json格式数据
*@Field用于post表单字段, Field和FieldMa需要FormUrlEncoded结合使用
*@FieldMapFiledMap和@Field作用一致,用于不确定表单参数
*@Part用于表单字段, Part和PartMap与Multipart注解配合,适合有文件上传的情况,FieldMap的接受类型是Map<String, String>, 非String类型会调用其toString方法。
*@PartMap用于表单字段,PartMap的默认接受类型是Map<String, RequestBody>, 非RequestBody类型会通过Convert转换,可用于实现多文件上传
*@Path用于URL占位 Query和QueryMap与Field和FieldMap功能一样,不同的是Query和QueryMap的数据体现在Url上, 而Field和FieldMap的数据是请求体,但生成的数据形式是一样的。
*@Query用于Get中指定参数
*@QueryMap和Query使用类似
*@Url指定请求路径

注1:{占位符}和PATH尽量只用在URL的path部分,url中的参数使用Query和QueryMap 代替,保证接口定义的简洁

注2: Query、Field和Part这三者都支持数组和实现了Iterable接口的类型,如List,Set等,方便向后台传递数组。

Call<ResponseBody> foo(@Query("ids[]") List<Integer> ids);
//结果:ids[]=0&ids[]=1&ids[]=2

用注解描述Http请求

  • 支持URL参数占位以及查询参数占位
  • 请求体的对象转换(例如json以及协议buffers)
  • 分片请求和文件上传

API定义

注解在接口方法上,参数声明了请求如何被处理

请求方法

每个方法必须有一个HTTP注解用于提供请求的方法和相对URL.有五种内置的注解请求方法:
GET,POST,PUT,DELETE,and HEAD.相对URL路径在注解内部.

@GET("users/list")

你也可以将查询参数放到URL中

@GET("users/list?sort=desc")

URL操作

请求的URL可以通过占位块和接口方法的参数进行动态更新, 格式如下:

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);

查询参数也可以放在接口方法中, 通过@Query注解实现

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);

对于复杂的查询参数可以用Map操作,代码格式如下:

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);

请求BODY

一个对象可以作为一个HTTP的请求体,通过@Body注解实现

@POST("users/new")
Call<User> createUser(@Body User user);

Retrofit实例中声明了转化器, 对象才可以被转化.如果没有添加转换器,只能用RequestBody

格式化编码和分片操作

请求接口也可以被定义为可以发送格式化编码和分片数据.
通过@FormUrlEncoded注解声明格式化编码的数据.每个键值对通过@Field注解声明.

@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);

分片请求通过注解@Multipart完成,示例代码如下:

@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

分片的片数据可以用Reftrofit定义的转换器,也可以通过实现RequestBody处理自己实现序列化.

头部操作

可以通过注解@Heather来设置静态的头信息

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);

相同头名称的字段不会相互覆盖,都会包含在头请求里, 头信息可以通过@Header注解动态更新, 头信息的值未null,则该头信息将被忽略,否则tostring被调用,然后用该函数转换后值.

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

同查询参数类似,复杂的头信息组合,可以用Map操作,示例代码如下:

@GET("user")
Call<User> getUser(@HeaderMap Map<String, String> headers)

每个请求都需要的头信息,可以在OkHttp 的拦截器中处理.

同步与异步

Call实例可以以同步或者异步方式执行.每个实例只能被执行一次,但是可以通过clone()方法创建一个新的实例来使用.在Android系统中,回调方法在主线程中执行.在JVM中,回调方法将在与执行HTTP请求线程相同的线程中执行.

Retrofit配置

Retrofit可以被配置.

3 转换器/Gson与Converter

默认情况下,Retrofit只可以反序列化Http bodies成OkHttp的ResponseBody类型, 仅仅接收RequestBody类型作为@Body参数.
这也是为什么我在前面的例子接口的返回值都是 Call,
但如果响应体只是支持转换为ResponseBody的话何必要引入泛型呢,
返回值直接用一个Call就行了嘛,既然支持泛型,那说明泛型参数可以是其它类型的,
而Converter就是Retrofit为我们提供用于将ResponseBody转换为我们想要的类型,
有了Converter之后我们就可以写把我们的第一个例子的接口写成这个样子了:

public interface BlogService {
  @GET("blog/{id}")
  Call<Result<Blog>> getBlog(@Path("id") int id);
}

当然只改变泛型的类型是不行的,我们在创建Retrofit时需要明确告知用于将ResponseBody转换我们泛型中的类型时需要使用的Converter

引入Gson支持:

compile 'com.squareup.retrofit2:converter-gson:2.0.2'

通过GsonConverterFactory为Retrofit添加Gson支持:

Gson gson = new GsonBuilder()
      //配置你的Gson
      .setDateFormat("yyyy-MM-dd hh:mm:ss")
      .create();

Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://localhost:4567/")
      //可以接收自定义的Gson,当然也可以不传
      .addConverterFactory(GsonConverterFactory.create(gson))
      .build();

这样Retrofit就会使用Gson将ResponseBody转换我们想要的类型。

这是时候我们终于可以演示如使创建一个Blog了!

@POST("blog")
Call<Result<Blog>> createBlog(@Body Blog blog);

被@Body注解的的Blog将会被Gson转换成RequestBody发送到服务器。

BlogService service = retrofit.create(BlogService.class);
Blog blog = new Blog();
blog.content = "新建的Blog";
blog.title = "测试";
blog.author = "怪盗kidou";
Call<Result<Blog>> call = service.createBlog(blog);

结果:

Result{code=200, msg='OK', data=Blog{id=20, date='2016-04-21 05:29:58', author='怪盗kidou', title='测试', content='新建的Blog'}, count=0, page=0}

下面以GsonConverterFactory类作为GitHubService的实现用于Gson的反序列化,示例代码如下:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

GitHubService service = retrofit.create(GitHubService.class);

定制转换器

如果你需要定制一个转化器用于解析诸如YAML,txt,自定义格式,或者你希望用一个不同的库来实现存在的格式,你可以通过集成Converter.Factory类来满足需求.

4 RxJava与CallAdapter

说到Retrofit就不得说到另一个火到不行的库RxJava,网上已经不少文章讲如何与Retrofit结合,但这里还是会有一个RxJava的例子,不过这里主要目的是介绍使用CallAdapter所带来的效果。

第3节介绍的Converter是对于Call中T的转换,而CallAdapter则可以对Call转换,这样的话Call中的Call也是可以被替换的,而返回值的类型就决定你后续的处理程序逻辑,同样Retrofit提供了多个CallAdapter,这里以RxJava的为例,用Observable代替Call:

引入RxJava支持:

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
// 针对rxjava2.x(adapter-rxjava2的版本要 >= 2.2.0)
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

通过RxJavaCallAdapterFactory为Retrofit添加RxJava支持:

Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://localhost:4567/")
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
      // 针对rxjava2.x
      .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 
      .build();

接口设计:

public interface BlogService {
  @POST("/blog")
  Observable<Result<List<Blog>>> getBlogs();
}

使用:

BlogService service = retrofit.create(BlogService.class);
service.getBlogs(1)
  .subscribeOn(Schedulers.io())
  .subscribe(new Subscriber<Result<List<Blog>>>() {
      @Override
      public void onCompleted() {
        System.out.println("onCompleted");
      }

      @Override
      public void onError(Throwable e) {
        System.err.println("onError");
      }

      @Override
      public void onNext(Result<List<Blog>> blogsResult) {
        System.out.println(blogsResult);
      }
  });

结果:

Result{code=200, msg='OK', data=[Blog{id=1, date='2016-04-15 03:17:50', author='怪盗kidou', title='Retrofit2 测试1', content='这里是 Retrofit2 Demo 测试服务器1'},.....], count=20, page=1}

像上面的这种情况最后我们无法获取到返回的Header和响应码的,如果我们需要这两者,提供两种方案:
1、用

Observable<Response<T>>

代替

Observable<T>

,这里的Response指retrofit2.Response.

2、用

Observable<Result<T>>

代替

Observable<T>

,这里的Result是指retrofit2.adapter.rxjava.Result,这个Result中包含了Response的实例.

5 自定义Converter

本节的内容是教大家实现在一简易的Converter,这里以返回格式为Call为例。

在此之前先了解一下Converter接口及其作用:

public interface Converter<F, T> {
  // 实现从 F(rom) 到 T(o)的转换
  T convert(F value) throws IOException;

  // 用于向Retrofit提供相应Converter的工厂
  abstract class Factory {
    // 这里创建从ResponseBody其它类型的Converter,如果不能处理返回null
    // 主要用于对响应体的处理
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
    Retrofit retrofit) {
      return null;
    }

    // 在这里创建 从自定类型到ResponseBody 的Converter,不能处理就返回null,
    // 主要用于对Part、PartMap、Body注解的处理
    public Converter<?, RequestBody> requestBodyConverter(Type type,
    Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }

    // 这里用于对Field、FieldMap、Header、Path、Query、QueryMap注解的处理
    // Retrfofit对于上面的几个注解默认使用的是调用toString方法
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
    Retrofit retrofit) {
      return null;
    }

  }
}

我们要想从Call 转换为 Call 那么对应的F和T则分别对应ResponseBody和String,我们定义一个StringConverter并实现Converter接口。

public static class StringConverter implements Converter<ResponseBody, String> {

  public static final StringConverter INSTANCE = new StringConverter();

  @Override
  public String convert(ResponseBody value) throws IOException {
    return value.string();
  }
}

我们需要一个Fractory来向Retrofit注册StringConverter

public static class StringConverterFactory extends Converter.Factory {

  public static final StringConverterFactory INSTANCE = new StringConverterFactory();

  public static StringConverterFactory create() {
    return INSTANCE;
  }

  // 我们只关实现从ResponseBody 到 String 的转换,所以其它方法可不覆盖
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
    if (type == String.class) {
      return StringConverter.INSTANCE;
    }
    //其它类型我们不处理,返回null就行
    return null;
  }
}

使用Retrofit.Builder.addConverterFactory向Retrofit注册我们StringConverterFactory:

Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://localhost:4567/")
      // 我们自定义的一定要放在Gson这类的Converter前面 
      .addConverterFactory(StringConverterFactory.create())
      .addConverterFactory(GsonConverterFactory.create())
      .build();

注: addConverterFactory是有先后顺序的,如果有多个ConverterFactory都支持同一种类型,那么就是只有第一个才会被使用,而GsonConverterFactory是不判断是否支持的,所以这里交换了顺序还会有一个异常抛出,原因是类型不匹配。

只要返回值类型的泛型参数就会由我们的StringConverter处理,不管是Call还是Observable

有没有很简单?如果你有其它的需求处理的就自己实现吧。

6 自定义CallAdapter

本节将介绍如何自定一个CallAdapter,并验证是否所有的String都会使用我们第5节中自定义的Converter。

先看一下CallAdapter接口定义及各方法的作用:

public interface CallAdapter<T> {

  // 直正数据的类型 如Call<T> 中的 T
  // 这个 T 会作为Converter.Factory.responseBodyConverter 的第一个参数
  // 可以参照上面的自定义Converter
  Type responseType();

  <R> T adapt(Call<R> call);

  // 用于向Retrofit提供CallAdapter的工厂类
  abstract class Factory {
    // 在这个方法中判断是否是我们支持的类型,returnType 即Call<Requestbody>和`Observable<Requestbody>`
    // RxJavaCallAdapterFactory 就是判断returnType是不是Observable<?> 类型
    // 不支持时返回null
    public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,
    Retrofit retrofit);

    // 用于获取泛型的参数 如 Call<Requestbody> 中 Requestbody
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    // 用于获取泛型的原始类型 如 Call<Requestbody> 中的 Call
    // 上面的get方法需要使用该方法。
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}

了解了CallAdapter的结构和其作用之后,我们就可以开始自定义我们的CallAdapter了,本节以CustomCall为例。

在此我们需要定义一个CustomCall,不过这里的CustomCall作为演示只是对Call的一个包装,并没有实际的用途。

public static class CustomCall<R> {

  public final Call<R> call;

  public CustomCall(Call<R> call) {
    this.call = call;
  }

  public R get() throws IOException {
    return call.execute().body();
  }
}

有了CustomCall,我们还需要一个CustomCallAdapter来实现 Call 到 CustomCall的转换,这里需要注意的是最后的泛型,是我们要返回的类型。

public static class CustomCallAdapter implements CallAdapter<CustomCall<?>> {

  private final Type responseType;

  // 下面的 responseType 方法需要数据的类型
  CustomCallAdapter(Type responseType) {
    this.responseType = responseType;
  }

  @Override
  public Type responseType() {
    return responseType;
  }

  @Override
  public <R> CustomCall<R> adapt(Call<R> call) {
    // 由 CustomCall 决定如何使用
    return new CustomCall<>(call);
  }
}

提供一个CustomCallAdapterFactory用于向Retrofit提供CustomCallAdapter:

public static class CustomCallAdapterFactory extends CallAdapter.Factory {
  public static final CustomCallAdapterFactory INSTANCE = new CustomCallAdapterFactory();

  @Override
  public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    // 获取原始类型
    Class<?> rawType = getRawType(returnType);
    // 返回值必须是CustomCall并且带有泛型
    if (rawType == CustomCall.class && returnType instanceof ParameterizedType) {
      Type callReturnType = getParameterUpperBound(0, (ParameterizedType) returnType);
      return new CustomCallAdapter(callReturnType);
    }
    return null;
  }
}

使用addCallAdapterFactory向Retrofit注册CustomCallAdapterFactory

Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://localhost:4567/")
      .addConverterFactory(Example09.StringConverterFactory.create())
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(CustomCallAdapterFactory.INSTANCE)
      .build();

注: addCallAdapterFactory与addConverterFactory同理,也有先后顺序。

7 其它说明

7.1 Retrofit.Builder

前面用到了 Retrofit.Builder 中的baseUrl、addCallAdapterFactory、addConverterFactory、build方法,还有callbackExecutor、callFactory、client、validateEagerly这四个方法没有用到,这里简单的介绍一下。

方法用途
callbackExecutor(Executor)指定Call.enqueue时使用的Executor,所以该设置只对返回值为Call的方法有效
callFactory(Factory)设置一个自定义的okhttp3.Call.Factory,那什么是Factory呢?OkHttpClient就实现了okhttp3.Call.Factory接口,下面的client(OkHttpClient)最终也是调用了该方法,也就是说两者不能共用
client(OkHttpClient)设置自定义的OkHttpClient,以前的Retrofit版本中不同的Retrofit对象共用同OkHttpClient,在2.0各对象各自持有不同的OkHttpClient实例,所以当你需要共用OkHttpClient或需要自定义时则可以使用该方法,如:处理Cookie、使用stetho 调式等
validateEagerly(boolean)是否在调用create(Class)时检测接口定义是否正确,而不是在调用方法才检测,适合在开发、测试时使用

7.2 Retrofit的Url组合规则

  • 如果你在注解中提供的url是完整的url,则url将作为请求的url。
  • 如果你在注解中提供的url是不完整的url,且不以 / 开头,则请求的url为baseUrl+注解中提供的值
  • 如果你在注解中提供的url是不完整的url,且以 / 开头,则请求的url为baseUrl的主机部分+注解中提供的值

7.3 Retrofit中提供的Convert

ConverterGradle依赖
Gsoncom.squareup.retrofit2:converter-gson:2.0.2
Jacksoncom.squareup.retrofit2:converter-jackson:2.0.2
Moshicom.squareup.retrofit2:converter-moshi:2.0.2
Protobufcom.squareup.retrofit2:converter-protobuf:2.0.2
Wirecom.squareup.retrofit2:converter-wire:2.0.2
Simple XMLcom.squareup.retrofit2:converter-simplexml:2.0.2
Scalarscom.squareup.retrofit2:converter-scalars:2.0.2

7.4 Retrofit提供的CallAdapter:

CallAdapterGradle依赖
guavacom.squareup.retrofit2:adapter-guava:2.0.2
Java8com.squareup.retrofit2:adapter-java8:2.0.2
rxjavacom.squareup.retrofit2:adapter-rxjava:2.0.2

8 参考连接

你真的会用Retrofit2吗?Retrofit2完全教程

你真的会用Retrofit2吗?Retrofit2完全教程Github Demo

Android 手把手教你使用Retrofit

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Retrofit 是一个开源的 Android 网络请求库,它简化了与 RESTful API 进行交互的过程。你可以使用 Retrofit 来发送网络请求并处理服务器返回的数据。 下面是使用 Retrofit 的一般步骤: 1. 添加 Retrofit 依赖:在你的项目中的 build.gradle 件中添加以下依赖: ```groovy implementation 'com.squareup.retrofit2:retrofit:2.x.x' ``` 2. 创建 API 接口:定义一个接口来描述你要访问的 API 端点和请求方法。例如: ```java public interface ApiService { @GET("users/{username}") Call<User> getUser(@Path("username") String username); } ``` 3. 创建 Retrofit 实例:使用 Retrofit.Builder 类构建一个 Retrofit 实例,配置基本的 URL 和转换器等。 ```java Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); ``` 4. 创建 API 服务:使用 Retrofit 实例创建一个实现了你的 API 接口的服务。 ```java ApiService apiService = retrofit.create(ApiService.class); ``` 5. 发送网络请求:通过调用 API 服务的方法发送网络请求,并处理返回的结果。 ```java Call<User> call = apiService.getUser("CSDN"); call.enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if (response.isSuccessful()) { User user = response.body(); // 处理返回的用户数据 } else { // 处理请求失败情况 } } @Override public void onFailure(Call<User> call, Throwable t) { // 处理请求失败情况 } }); ``` 这只是一个简单的示例,你可以根据自己的需求进行更复杂的网络请求和数据处理。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Calvin880828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值