Изменен базовый уровень модернизации в режиме Runtime с использованием кинжала 2 [дубликат]

Закон большой тройки такой, как указано выше.

Легкий пример на простом английском языке той проблемы, которую он решает:

Неисправный деструктор

]

Вы выделили память в своем конструкторе, и вам нужно написать деструктор, чтобы удалить его. В противном случае произойдет утечка памяти.

Вы можете подумать, что это работа.

Проблема будет, если копия сделана из вашего объекта, то копия укажет на ту же память, что и на исходный объект.

Однажды один из них удаляет память в своем деструкторе другой будет иметь указатель на недопустимую память (это называется обвисший указатель), когда он пытается использовать его, все будет выглядеть волосатым.

Поэтому вы пишете конструктор копирования, чтобы он выделяет новые объекты для уничтожения своих собственных фрагментов памяти.

Оператор присваивания и конструктор копирования

Вы выделили память в своем конструкторе указателю участника вашего класса. Когда вы копируете объект этого класса, оператор присваивания по умолчанию и конструктор копирования копируют значение этого элемента-указателя на новый объект.

Это означает, что новый объект и старый объект будут указывать на тот же кусок памяти, поэтому, когда вы меняете его на один объект, он будет изменен и для другого объекта objerct. Если один объект удаляет эту память, другой будет продолжать пытаться ее использовать - eek.

Чтобы решить эту проблему, вы пишете собственную версию конструктора копирования и оператора присваивания. Ваши версии выделяют отдельную память новым объектам и копируют значения, на которые указывает первый указатель, а не его адрес.

7
задан JakubW 21 April 2016 в 12:47
поделиться

2 ответа

Здесь я вижу 2 варианта:

  • Используйте кинжал, как он предназначен. Создайте для каждого baseUrl свой собственный клиент Retrofit или
  • Используйте перехватчик для изменения запроса перед его отправкой

Подход кинжала

Если бы вы использовали URL-адреса грубой силы, это, вероятно, не было бы правильным выбором, поскольку он полагался на создание нового экземпляра Retrofit для каждого.

Теперь каждый раз, когда URL-адрес изменяется, вы просто воссоздаете после демонстрации UrlComponent путем подачи его новым UrlModule.

Очистить

Очистить модуль @Singleton, чтобы он обеспечивал GsonConverterFactory и RxJavaCallAdapterFactory для правильного использования кинжала и не воссоздать общие объекты.

@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 Scoped

Представьте @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 Implem введите MyApiInterceptor. Вам нужно будет установить сеттер для базового url, а затем просто переписать / изменить запросы, проходящие через.

Затем снова запустите и используйте его.

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-адрес и я добавил это последнее только для полноты.

9
ответ дан David Medenjak 27 August 2018 в 00:10
поделиться

Вы можете реализовать BaseUrl и передать это вместо фиксированного URL. проверить эту ссылку . Другой подход реализует Endpoint и использует setUrl(). Поэтому для изменения некоторого значения заголовка во время выполнения вы можете использовать перехватчик и добавить его в OkHttp.

5
ответ дан Godfather 27 August 2018 в 00:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: