Я учусь использовать Dagger2 и MVP , поэтому я создал проект, содержащий одно основное действие с viewPager
и два фрагмента.
Кодработает, но я думаю, что делаю что-то не так, когда создаю свои классы Dagger.Я думаю, если я продолжу, создать монстра =)
Я прошу вас помочь прокомментировать мою архитектуру кода, связанную с Dagger2.Может быть, этот вопрос должен быть на CodeReview: если так, я делаю и переместить его.
Хорошо, я покажу это шаг за шагом.Основные подозрения на плохой код на шаге 3.
На первом этапе основное действие называется HomeActivity
, а фрагмент (я его покажу) - HomePacksFragment
.Приложение о животных, и фрагмент показывает пакеты их, поэтому он называется так.
1) У меня есть два модуля: PresentersModule
, предоставить докладчиков для HomeActivity
и HomePacksFragment
:
@Module
public class PresentersModule {
@Provides
HomePresenter provideHomePresenter(AnimalDatabase animalDatabase) {
return new HomePresenter(animalDatabase);
}
@Provides
HomePacksFragmentPresenter provideHomePacksFragmentPresenter(AnimalDatabase animalDatabase) {
return new HomePacksFragmentPresenter(animalDatabase);
}
}
и RoomModule
расширенный доступ к базе данных и DAO:
@Module
public class RoomModule {
private AnimalDatabase db;
public RoomModule(Application mApplication) {
db = Room.databaseBuilder(mApplication,
AnimalDatabase.class, AnimalDatabase.DATABASE_NAME)
.allowMainThreadQueries()
.fallbackToDestructiveMigration()
.build();
}
@Singleton
@Provides
AnimalDatabase providesRoomDatabase() {
return db;
}
@Singleton
@Provides
DAO providesProductDao(AnimalDatabase db) {
return db.daoAccess();
}
}
2) Тогда у меня есть компонент AppComponent
, который знает все мои модули и может внедрять зависимости в конкретном представлении:
@Singleton
@Component(modules = {PresentersModule.class, RoomModule.class})
public interface AppComponent {
void injectsHomeActivity(HomeActivity homeActivity);
void injectsHomePacksFragment(HomePacksFragment homePacksFragment);
DAO animalDao();
AnimalDatabase animalDatabase();
}
3) Тогда у меня есть класс AnimalsLibraryApp
, расширенный Application
, и это место, которое я ошибаюсь, по моему мнению.
public class AnimalsLibraryApp extends Application {
private static AnimalsLibraryApp instance;
private static AppComponent homeActivityComponent;
private static AppComponent homeFragmentPacksComponent;
@Override
public void onCreate() {
super.onCreate();
instance = this;
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
}
createHomeActivityComponent();
createHomePacksComponent();
}
public static AnimalsLibraryApp getInstance() {
return instance;
}
public static AppComponent getHomeActivityComponent() {
return homeActivityComponent;
}
public static AppComponent getHomeFragmentPacksComponent() {
return homeFragmentPacksComponent;
}
private void createHomeActivityComponent() {
homeActivityComponent = DaggerAppComponent.builder()
.presentersModule(new PresentersModule())
.roomModule(new RoomModule(instance))
.build();
}
private void createHomePacksComponent() {
homeFragmentPacksComponent = DaggerAppComponent.builder()
.presentersModule(new PresentersModule())
.roomModule(new RoomModule(instance))
.build();
}
}
Идея этого класса заключалась в том, чтобы предоставить единственные приложения AppComponent.Технически это работает, но что если у меня 10 или 20 просмотров?Класс расширенный Application
является базовым классом, он не будет содержать только AppComponent
логики создания, и многое другое будет здесь.Я правильно пишу?
4) Это конец.Я создаю HomeActivity
и внедряю зависимости с помощью простой (не так ли) строки.
public class HomeActivity extends AppCompatActivity implements HomeContract.View {
@Inject
HomePresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
AnimalsLibraryApp.getHomeActivityComponent().injectsHomeActivity(this);
presenter.attachView(this);
presenter.viewIsReady();
DatabaseUtils.copyDatabase(this, AnimalDatabase.DATABASE_NAME);
ViewPager viewPager = findViewById(R.id.pager);
HomeMenuAdapter myPagerAdapter = new HomeMenuAdapter(getSupportFragmentManager());
viewPager.setAdapter(myPagerAdapter);
TabLayout tabLayout = findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.help);
tabLayout.getTabAt(1).setIcon(R.drawable.help);
}
}
Я делаю правильные вещи или я должен что-то изменить, пока не стало слишком поздно?
UPD:
Хорошо, я заглянул в простой пример Dagger 2 и нашел эту App
версию класса:
public class MyApp extends Application {
private static MyApp app;
private AppModule appModule;
private BasicComponent basicComponent;
@Override
public void onCreate() {
super.onCreate();
app = this;
appModule = new AppModule(this);
basicComponent = DaggerBasicComponent.builder()
.appModule(appModule)
.build();
}
public static MyApp app() {
return app;
}
public AppModule appModule() {
return appModule;
}
public BasicComponent basicComponent() {
return basicComponent;
}
Это выглядит лучше и чище, чем мой, но у меня есть вопрос.В этом примере мы всегда возвращаем basicComponent, так что это означает, что он должен включать все модули?Это нормальная практика, чтобы создать "бог" компонент?=)
Если у меня есть 3 модуля, мне нужно написать (для моего примера):
appComponent = DaggerAppComponent
.builder()
.appModule(appModule)
.presentersModule(new PresentersModule())
.roomModule(new RoomModule(this))
.build();