android - Dagger2 的项目结构

标签 android dagger-2

我正在学习如何使用Dagger2MVP,所以我创建了一个项目,包含一个带有viewPager的主要 Activity 和两个 fragment 。

代码正在运行,但我认为在创建 Dagger 类时我做错了什么。我想如果我继续,就会创造一个怪物 =)

我请求您帮助评论我与 Dagger2 相关的代码架构。也许这个问题应该放在 CodeReview 上:如果是这样,我删除并移动它。

好的,我一步步展示。主要怀疑是第 3 步中的错误代码。

首先,主 Activity 称为 HomeActivity, fragment (我展示了一个)称为 HomePacksFragment。关于动物的应用程序,并且 fragment 显示它们的包,这就是它如此命名的原因。

1)我有两个模块:PresentersModule,为HomeActivityHomePacksFragment提供演示者:

@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,它知道我的所有模块并且可以在具体 View 中注入(inject)依赖项:

@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 并使用简单的(不是吗?)行注入(inject)依赖项。

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);
    }
}

我做了正确的事情,或者我必须改变一些事情,直到为时不晚?

更新:

好的,我在 google 上搜索了简单的 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();

最佳答案

根据我的想法和您所说的引用资料,您使用 AnimalsLibraryApp 的方式很糟糕。 在应用程序类中,您只需要声明一个 dagger 组件,然后在每个 View 中,您将在 View 中注入(inject)带有该组件的模块。 如果您用 google 搜索 dagger2 示例并检查扩展应用程序的类,您就会理解。

关于android - Dagger2 的项目结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54958483/

相关文章:

android - Android 的 UI 自动化测试

android - Dagger2 禁用 AndroidInjection.inject(this);用于仪器测试

java - Dagger 2 : how to inject retrofit module in presenter class

android - 在相对布局中创建布局

android - 为什么 Android.mk 文件中的 $(call my-dir) 返回了错误的路径?

java - Android 水平线性布局 - 包装元素

android - Dagger 2.10 Android 子组件和构建器

android - Dagger 2 - 注入(inject)构造函数或提供方法哪个更好?

java - Dagger 使用 Provides 与创建自定义类

php - 如何从外部服务器播放 BLOB 中的音频流?