美文网首页androidAndroid知识Android开发
Retrofit2-如何在请求时使用动态URL

Retrofit2-如何在请求时使用动态URL

作者: sheepm | 来源:发表于2016-09-24 15:26 被阅读17082次

    Retrofit2为动态url带来的新的注解,在Retrofit 1中迷惑的点现在只需要一个 Url 注解就能描述结点(endpoint)。
    这篇文章将会展示如何利用动态结点url处理单独的请求。

    原文地址

    Retrofit 2 — How to Use Dynamic Urls for Requests

    使用案例情况

    这里有两个案例来说明真实的应用场景。

    • 图片详情:如果你的app允许用户上传他们自己的个人头像,你可能需要将这些文件储存在不同的地方比如你自己的服务器,Amazon S3(亚马逊云服务)或者是Gravatar(Globally Recognized Avatar)
    • 文件下载:文件可以被存储在多个地方而且你希望从任何资源地址灵活的下载内容

    即使你的app没有任何建议的功能,你也可以可以适当的想象一个适合动态URL使用的例子。

    怎么使用动态URLs

    实际上,它只需要你加入一个单独的注解 @Url 在你的定义的结点,一图胜千言

    public interface UserService {  
        @GET
        public Call<ResponseBody> profilePicture(@Url String url);
    }
    

    可以看到,在 GET 上不需要结点url,我们可以直接在方法中去添加这个url

    Urls是怎么针对base url解析的

    有另外一个有趣而且需要注意的地方:动态url是怎么在已经定义base Url的情况下被解析的,Retrofit 2使用OkHttp的 HttpUrl 而且解析任何URL结点成类似一个网址的链接。
    让我们根据一些场景来明白这个过程,首先我们有一个url指向Amazon S3(注:一个云服务平台,类似七牛)中存储的一个图片地址,而且我们也已经定义了一个base Url,这两个的地址是完全不一样的,

    Retrofit retrofit = Retrofit.Builder()  
        .baseUrl("https://your.api.url/");
        .build();
    
    UserService service = retrofit.create(UserService.class);  
    service.profilePicture("https://s3.amazon.com/profile-picture/path");
    
    // request url results in:
    // https://s3.amazon.com/profile-picture/path
    

    因为你设置了一个完全不同的包含scheme的host (https://s3.amazon.com vs. https://your.api.url) ,OkHttp的HttpUrl会解析它成我们设置的url,这个和我们所定义的base Url并没有关系。
    第二个例子:这次我们指定动态url在我们已经定义的base Url同一个服务下面,比如下面的代码

    Retrofit retrofit = Retrofit.Builder()  
        .baseUrl("https://your.api.url/");
        .build();
    
    UserService service = retrofit.create(UserService.class);  
    service.profilePicture("profile-picture/path");
    
    // request url results in:
    // https://your.api.url/profile-picture/path
    

    这次,这个最终的请求url被会我们定义的base Url和动态结点url联系起来,HttpUrl(OkHttp)会意识到我们没有指定一个scheme和host,因此这个url结点会被加到base Url的后面。
    第三个例子:我们假设后端开发发布了一个更新版本v2,并且和原来的base Url冲突了,比如下面的例子

    Retrofit retrofit = Retrofit.Builder()  
        .baseUrl("https://your.api.url/v2/");
        .build();
    
    UserService service = retrofit.create(UserService.class);  
    service.profilePicture("/profile-picture/path");
    
    // request url results in:
    // https://your.api.url/profile-picture/path
    

    第二和第三个例子的不同点就是:我们添加了一个 v2/ 到base url后面并且在结点url的前面添加了一个 / 。实际上这将会最终生成同样的url,因为结点url的前面是一个 / 符号,这个将会只添加到base Url的host上面。当我们在结点url上添加一个前置 / 符号时,每个加到host Url后面的东西都会被省略掉。删除前置 / 有时候可以解决你的一些不明白的问题。

    分析提示

    正确的“创建”请求url是你需要注意的问题。这些文章中的例子展示了一些容易犯的错误,一不小心就可能陷入这个陷阱中,确保你在请求时使用了一个完全的url(包括scheme,host,path),否则你不得不去考虑上面的这些场景。

    相关文章

      网友评论

      • JessYan:感谢博主的分享,个人感觉 @Url 虽然灵活性扩展性都极强,但是每个方法在请求时不管需不需要替换为新的 Url 都需要传入一个 Url 地址,比较繁琐,如果只有一两个 API 还好,但如果用在某些需要大量使用此功能的项目的话还是需要一定的工作量的,于是本人写了一个库,可以更加方便的管理多个 BaseUrl,只有在需要改变 BaseUrl 的时候才调用一次 API,同时和 @Url 一样,也同样支持在运行中随时的动态改变 Url,分享出来,希望能帮助到更多有同样需求的朋友,https://github.com/JessYanCoding/RetrofitUrlManager,开源不易,不喜勿喷
        2615e92f0121:@JessYan 嗯,支持大佬,开源不易~
        JessYan:@一个不务正业的程序员 我只是在使用拦截器改变 baseUrl 的文章下留下了评论,这个方案是我的首发,因为一个 csdn 的博主,抄袭我的文章,没有给予原文地址不说,还将代码改得降低了扩展性,误导了不少人,这个 csdn 博主已经删除了文章,还有一些被他误导的博主也根据这个思想发布了同样的文章,我当然要在下面留言告诉他们,原文地址,并且告诉他们此方案已开源,不必自己去管理,https://github.com/JessYanCoding
        2615e92f0121:@JessYan 你的开源方案我看了,确实写的还是不错的,但是我发现在类似的文章下面,基本上都有你的评论。。
      • 0a2868f025e0:接入@url直接报错
        coolzpw:post 应该咋搞啊? 有人解决了吗?
      • 0a2868f025e0:直接报错啊
      • 丶Mdzz:post请求能这样@url使用吗?
      • Xdjm:谢谢,用url解决了path传值error的问题
        :smile:
        d95f3d04f629:确实是啊,如果用path的话/会被转义
      • Jey欧巴:你好楼主,请问动态的url地址请求,如果这个地址带参数怎么传进去?
        IOwl:可以先把参数组起来吧

      本文标题:Retrofit2-如何在请求时使用动态URL

      本文链接:https://www.haomeiwen.com/subject/zizzettx.html