草庐IT

android - Dagger + 改造动态 URL

coder 2023-11-25 原文

问题

我需要从 USER 输入的域调用 API,并且我需要在调用之前根据插入的数据编辑我的 Retrofit 单例。

有没有办法“重置”我的单例,迫使它重新创建?

有没有办法在调用之前用我的数据(可能在拦截器中?)更新我的 baseUrl

代码

单例

@Provides
@Singleton
Retrofit provideRetrofit(SharedPreferences prefs) {

    String apiUrl = "https://%1s%2s";
    apiUrl = String.format(apiUrl, prefs.getString(ACCOUNT_SUBDOMAIN, null), prefs.getString(ACCOUNT_DOMAIN, null));

    OkHttpClient httpClient = new OkHttpClient.Builder()
            .addInterceptor(new HeaderInterceptor())
            .build();

    return new Retrofit.Builder()
            .baseUrl(apiUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .client(httpClient)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
}

@Provides
@Singleton
API provideAPI(Retrofit retrofit) {
    return retrofit.create(API.class);
}

API

@FormUrlEncoded
@POST("endpoint")
Observable<Response> logIn(@Field("login") String login, @Field("password") String password);

现在如何运作

我们的想法是在 API 调用之前通过 SharedPrefs 保存用户域数据,并使用格式化的字符串修改 baseUrl

最佳答案

我在这里看到 2 个选项:

  • 按预期使用 Dagger 。为每个 baseUrl 创建自己的 Retrofit 客户端,或者
  • 在发送之前使用拦截器修改请求

Dagger 法

如果您要暴力破解 URL,这可能不是正确的选择,因为它依赖于为每个 URL 创建一个新的 Retrofit 实例。

现在每次 url 更改时,您只需重新创建以下演示的 UrlComponent,方法是为其提供新的 UrlModule

清理

清理您的@Singleton 模块,使其提供GsonConverterFactoryRxJavaCallAdapterFactory 以正确使用dagger 而不是重新创建共享对象。

@Module
public class SingletonModule {

  @Provides
  @Singleton
  GsonConverterFactory provideOkHttpClient() {/**/}

  @Provides
  @Singleton
  RxJavaCallAdapterFactory provideOkHttpClient() {/**/}
}


@Singleton
@Component(modules = SingletonModule.class)
interface SingletonComponent {

    // sub component
    UrlComponent plus(UrlModule component);
}

URL 范围

引入一个 @UrlScope 来限定您的 Retrofit 实例。

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface UrlScope {
}

然后创建一个子组件

@SubComponent(modules=UrlModule.class)
public interface UrlComponent {}

还有一个模块

@Module
class UrlModule {

    private final String mUrl;

    UrlModule(String url) { mUrl = url; }

    @Provides
    String provideUrl() {
        return mUrl;
    }

    @Provides
    @UrlScope
    OkHttpClient provideOkHttpClient(String url) {
        return new OkHttpClient.Builder().build();
    }

    @Provides
    @UrlScope
    Retrofit provideRetrofit(OkHttpClient client) {
        return new Retrofit.Builder().build();
    }

}

使用作用域Retrofit

实例化组件并使用它。

class Dagger {

    public void demo() {
        UrlModule module = new UrlModule(/*some url*/);
        SingletonComponent singletonComponent = DaggerSingletonComponent.create();
        UrlComponent urlComponent = singletonComponent.plus(module);

        urlComponent.getRetrofit(); // done.
    }
}

OkHttp 方法

提供一个适当范围的拦截器(在本例中为@Singleton)并实现相应的逻辑。

@Module
class SingletonModule {

    @Provides
    @Singleton
    GsonConverterFactory provideGsonConverter() { /**/ }

    @Provides
    @Singleton
    RxJavaCallAdapterFactory provideRxJavaCallAdapter() { /**/ }

    @Provides
    @Singleton
    MyApiInterceptor provideMyApiInterceptor() { /**/ }

    @Provides
    @Singleton
    OkHttpClient provideOkHttpClient(MyApiInterceptor interceptor) {
        return new OkHttpClient.Builder().build();
    }

    @Provides
    @Singleton
    Retrofit provideRetrofit(OkHttpClient client) {
        return new Retrofit.Builder().build();
    }
}

@Singleton
@Component(modules = SingletonModule.class)
interface SingletonComponent {

    Retrofit getRetrofit();

    MyApiInterceptor getInterceptor();
}

todo 实现 MyApiInterceptor。您需要为基本 url 设置一个 setter,然后只需重写/修改通过的请求。

然后,再一次,继续使用它。

class Dagger {

    public void demo() {
        SingletonComponent singletonComponent = DaggerSingletonComponent.create();
        MyService service = singletonComponent.getRetrofit().create(MyService.class);
        MyApiInterceptor interceptor = singletonComponent.getInterceptor();

        interceptor.setBaseUrl(myUrlA);
        service.doA();
        interceptor.setBaseUrl(someOtherUrl);
        service.doB();
    }
}

作为第三种方法,您还可以使用反射 直接更改基本 URL——我最后添加这个只是为了完整性。

关于android - Dagger + 改造动态 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36769923/

有关android - Dagger + 改造动态 URL的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  3. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  4. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  5. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  6. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. ruby-on-rails - Rails - 使用/自定义 URL : '/dashboard' 指定根路径 - 2

    如何使此根路径转到:“/dashboard”而不仅仅是http://example.com?root:to=>'dashboard#index',:constraints=>lambda{|req|!req.session[:user_id].blank?} 最佳答案 您可以通过以下方式实现:root:to=>redirect('/dashboard')match'/dashboard',:to=>"dashboard#index",:constraints=>lambda{|req|!req.session[:user_id].b

  9. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  10. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

随机推荐