К сожалению, Dagger - это круто, и я пытаюсь внедрить его дооснащение. Я ввел Context и SharedPreferences, и он работает нормально, но Retrofit сломал все это. Он распознает класс DaggerRetrofitComponent, но не находит DaggerAppComponent.
Модуль модернизации:
@Module
public class RetrofitModule {
public static final String BASE_URL = "http://api.themoviedb.org/3/";
@Provides
HttpLoggingInterceptor getHttpLoggingInterceptor(){
return new HttpLoggingInterceptor();
}
@Provides
OkHttpClient getOkHttpClient(HttpLoggingInterceptor interceptor){
return new OkHttpClient.Builder().addInterceptor(interceptor).build();
}
@Provides
GsonConverterFactory getGsonConverterFactory(){
return GsonConverterFactory.create();
}
@Provides
Retrofit getRetrofit(GsonConverterFactory gsonConverterFactory, OkHttpClient client){
return new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(gsonConverterFactory)
.client(client).build();
}
}
Заявление:
public class MyApplication extends Application {
private static AppComponent appComponent;
public static AppComponent getAppComponent(){
return appComponent;
}
@Override
public void onCreate() {
super.onCreate();
appComponent=buildComponent();
}
protected AppComponent buildComponent(){
if (BuildConfig.DEBUG){
Timber.plant(new Timber.DebugTree());
}
return DaggerAppComponent.builder().sharedPreferenceModule(new SharedPreferenceModule()).contextModule(new ContextModule(this)).build();
}
}
AppComponent:
@Singleton
@Component(modules = {ContextModule.class, SharedPreferenceModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
}
Компонент модернизации:
@Singleton
@Component(modules = {RetrofitModule.class})
public interface RetrofitComponent {
void injectRetrofit(Activity activity);
//
}
Основная деятельность:
public class MainActivity extends AppCompatActivity {
@Inject
Context context;
@Inject
SharedPreferences sharedPreferences;
@Inject
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerRetrofitComponent.builder().retrofitModule(new RetrofitModule()).build().injectRetrofit(this);
MyApplication.getAppComponent().inject(this);
}
}
Dagger 2 не позволяет вводить зависимости от нескольких компонентов. Вам следует подумать об использовании подкомпонентов.
https://google.github.io/dagger/subcomponents.html
UPD: Я бы посоветовал вам создать подкомпонент, производный от вашего AppComponent, например NetComponent. А затем укажите getNetComponent.inject () в своей деятельности. Поскольку NetComponent будет производным от AppComponent, он предоставит все зависимости от appComponent, которые вам нужны.
Это немного сложнее, но это правильный способ сделать это, также вы должны узнать о Dagger Scopes.
ИЛИ ЖЕ
Быстрый способ - просто поместить ваши сетевые зависимости в AppComponent.
Я не уверен, почему вы хотите модифицировать компонент (модуля из вашего компонента приложения должно быть достаточно), тогда вы должны использовать последнюю версию Dagger для обработки автоматической инъекции для представлений вашего контроллера (действий и фрагментов)
@Singleton
@Component(modules = [ApplicationModule::class])
interface ApplicationComponent : AndroidInjector<MyApplication>
{
override fun inject(application: MyApplication)
@Component.Builder
interface Builder
{
@BindsInstance
fun application(application: MyApplication): Builder
fun build(): ApplicationComponent
}
}
__
@Module(includes = [AndroidSupportInjectionModule::class,ActivityBuilderModule::class, NetworkModule::class])
abstract class ApplicationModule
{
@Binds
@Singleton
abstract fun bindApplication(application: MyApplication): Application
@Module
companion object
{
@Provides
@Singleton
@ApplicationContext
@JvmStatic
fun provideApplicationContext(application: MyApplication): Context = application
}
}
__
@Module
abstract class ActivityBuilderModule
{
@ContributesAndroidInjector(modules = [MainActivityModule::class])
@ActivityScope
abstract fun contributeMainActivity(): MainActivity
//others activities there
}
@Module
object NetworkModule
{
// For simplicity just retrofit provider, but all others network resources should be here of course
@Provides
@Singleton
@JvmStatic
fun provideRetrofit(rxJava2CallAdapterFactory: RxJava2CallAdapterFactory,
nullOrEmptyConverterFactory: Converter.Factory,
@ApplicationContext okHttpClient: OkHttpClient,
gsonConverterFactory: GsonConverterFactory): Retrofit =
Retrofit.Builder()
.addCallAdapterFactory(rxJava2CallAdapterFactory)
.addConverterFactory(nullOrEmptyConverterFactory)
.addConverterFactory(gsonConverterFactory)
.baseUrl(BASE_URL)
.client(okHttpClient)
.build()
}
__
class MyApplication : DaggerApplication()
{
private val applicationInjector = DaggerApplicationComponent.builder()
.application(this)
.build()
public override fun applicationInjector() = applicationInjector
}
__
Затем из ваших действий / фрагментов сделайте их унаследованными от DaggerActivity или DaggerFragment, и вы сможете делать свои инъекции из коробки.
Вы можете взглянуть на мой шаблонный проект https://github.com/SamYStudiO/beaver, он может помочь.
ps: Извините, это все kotlin, но его легко конвертировать в java
Что такое ActivityBuilderModule?
Я добавил его (полезно создавать подкомпоненты действий из компонента приложения), проверьте мою ссылку github внизу, если вы что-то пропустили, все исходит из этого
@JvmStatic - это просто аннотация, чтобы сообщить java, что это статический метод, поскольку kotlin не является статическим ключевым словом
MainActivityModule? Кажется, я не могу найти его в репозитории github
Вот он: github.com/SamYStudiO/beaver/blob/master/app/src/main/kotlin /…, если у вас есть определенные зависимости с вашим MainActivity, то куда их поместить.
Аннотации не допускаются перед сопутствующим объектом в модуле приложения. Я заменил сопутствующий объект статическим блоком.
Предназначен для преобразования в java, для каждого сопутствующего блока вы должны удалить их, удалить @JvmStatic и сделать метод статическим
Извините, это слишком сложно для меня как новичка, который только что узнал о модулях и поставках
Удалите этот класс:
//@Singleton
//@Component(modules = {RetrofitModule.class})
//public interface RetrofitComponent {
// void injectRetrofit(Activity activity);
//
//}
и изменим AppComponent:
@Singleton
@Component(modules = {ContextModule.class, SharedPreferenceModule.class, RetrofitModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
}
Это работает, но как разделить зависимости уровня приложения и уровня активности?
Модернизация не является зависимостью от уровня активности, она помечена @Singleton.
Да, я понял. Но не могли бы вы привести пример зависимостей на уровне активности (не обязательно дооснащение).
@Bissisingh, ваш докладчик для вашей деятельности, является примером зависимости в области действия.
@ mt0s Но могу ли я ввести ведущего, например, кроме того факта, что я могу сбрасывать все на уровне приложения, что не кажется хорошим.
Котлин не является проблемой, но я еще не изучал большинство этих аннотаций, таких как JVMstatic.