Закон большой тройки такой, как указано выше.
Легкий пример на простом английском языке той проблемы, которую он решает:
Неисправный деструктор
]Вы выделили память в своем конструкторе, и вам нужно написать деструктор, чтобы удалить его. В противном случае произойдет утечка памяти.
Вы можете подумать, что это работа.
Проблема будет, если копия сделана из вашего объекта, то копия укажет на ту же память, что и на исходный объект.
Однажды один из них удаляет память в своем деструкторе другой будет иметь указатель на недопустимую память (это называется обвисший указатель), когда он пытается использовать его, все будет выглядеть волосатым.
Поэтому вы пишете конструктор копирования, чтобы он выделяет новые объекты для уничтожения своих собственных фрагментов памяти.
Оператор присваивания и конструктор копирования
Вы выделили память в своем конструкторе указателю участника вашего класса. Когда вы копируете объект этого класса, оператор присваивания по умолчанию и конструктор копирования копируют значение этого элемента-указателя на новый объект.
Это означает, что новый объект и старый объект будут указывать на тот же кусок памяти, поэтому, когда вы меняете его на один объект, он будет изменен и для другого объекта objerct. Если один объект удаляет эту память, другой будет продолжать пытаться ее использовать - eek.
Чтобы решить эту проблему, вы пишете собственную версию конструктора копирования и оператора присваивания. Ваши версии выделяют отдельную память новым объектам и копируют значения, на которые указывает первый указатель, а не его адрес.
Здесь я вижу 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);
}
Представьте @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.
}
}
Обеспечьте в этом случае правильно перехваченный перехватчик (@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-адрес и я добавил это последнее только для полноты.
Вы можете реализовать BaseUrl
и передать это вместо фиксированного URL. проверить эту ссылку . Другой подход реализует Endpoint
и использует setUrl()
. Поэтому для изменения некоторого значения заголовка во время выполнения вы можете использовать перехватчик и добавить его в OkHttp.