Dagger2 преобразование в android.dagger

Я изучил некоторые учебники о новом подходе dagger.android, но не могу сделать это правильно. Я построил простое руководство с компоновщиком подкомпонентов, но я не могу преобразовать это в новый подход. Все учебники и статьи оставляют необходимые части пустыми.

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

Объем

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}   

Родительский компонент

@Component(modules = ApplicationModule.class)
@Singleton
public interface ApplicationComponent {

    // Calls SubComponent Builder from MainActivity using ApplicationComponent
    ToastMakerSubComponent.Builder toastMakerBuilder();
}

Родительский модуль, я не использовал @BindsInstance в модуле приложения для изучения различных подходов

@Module(subcomponents = {ToastMakerSubComponent.class})
public class ApplicationModule {

    private Context context;

    public ApplicationModule(Context context) {
        this.context = context;
    }

    @Provides
    @Singleton
    SharedPreferences provideSharedPreferences() {
        System.out.println("ApplicationModule context: " + context);
        return context.getSharedPreferences("PrefName", Context.MODE_PRIVATE);
    }
}

Подкомпонент

@ActivityScope
@Subcomponent(modules = {ToastMakerModule.class})
public interface ToastMakerSubComponent {
    void inject(MainActivity mainActivity);

    /*
     Builder is called from Parent Component,
      and parent component is called from scope(Activity, Fragment, etc.)
      */
    @Subcomponent.Builder
    interface Builder {

        ToastMakerSubComponent build();

        @BindsInstance
        Builder context(Context context);
    }
}

Подкомпонентный модуль

@Module
public class ToastMakerModule {

    @ActivityScope
    @Provides
    ToastMaker provideToastMaker(Context context) {
        System.out.println("ToastMakerModule context: " + context);
        return new ToastMaker(context);
    }
}

Создание экземпляра ApplicationComponent внутри MyApplication

 mApplicationComponent = DaggerApplicationComponent
                .builder()
                .applicationModule(new ApplicationModule(getApplicationContext()))
                .build();

И получить подкомпонент внутри Activity

ApplicationComponent applicationComponent = ((MyApplication) getApplication()).getApplicationComponent();

ToastMakerSubComponent toastMakerSubComponent = applicationComponent
        .toastMakerBuilder()
        .context(this)
        .build();

toastMakerSubComponent.inject(this);

После этого, этого и этого урока я построил следующее как

@Component(modules = ApplicationModule.class)
@Singleton
public interface ApplicationComponent {
// What should i put here ???

}

Родительский модуль, но я не понял, как мне предоставить provideSharedPreferences

@Module(subcomponents = {ToastMakerSubComponent.class})
abstract class ApplicationModule {

    @Binds
    @IntoMap
    @ActivityKey(MainActivity.class)
    abstract AndroidInjector.Factory<? extends MainActivity>
    bindYourActivityInjectorFactory(ToastMakerSubComponent.Builder builder);

}

Подкомпонент отсутствует ToastMakerSubComponent build(); а также @BindsInstance Builder context(Context context); как я должен добавить это к этому компоненту.

@ActivityScope
@Subcomponent(modules = {ToastMakerModule.class})
public interface ToastMakerSubComponent extends AndroidInjector<MainActivity> {
    // ??? Is this required?
    void inject(MainActivity mainActivity);

    @Subcomponent.Builder
     abstract class Builder extends AndroidInjector.Builder<MainActivity> {
         ???
    }
}

Также я вижу @ContributesAndroidInjectorгде это вписывается в этот пример?

1 ответ

Решение

Вот разница изменений: https://www.diffchecker.com/3IL8UQ7P

Расширить компонент приложения AndroidInjector<MyApplication> и включать AndroidSupportInjectionModule

@Component(modules = {ApplicationModule.class, AndroidSupportInjectionModule.class})
@Singleton
public interface ApplicationComponent extends AndroidInjector<MyApplication> {

}

Расширить подкомпонент AndroidInjector<MainActivity> и строитель AndroidInjector.Builder<MainActivity>использовать seedInstance предоставить аргументы @BindsInstance методы.

@ActivityScope
@Subcomponent(modules = {ToastMakerModule.class})
public interface ToastMakerSubComponent extends AndroidInjector<MainActivity> {

    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<MainActivity> {

        @Override
        public void seedInstance(MainActivity instance) {
            context(instance);
        }

        @BindsInstance
        public abstract Builder context(Context context);
    }
}

Добавьте привязку для компоновщика подкомпонента к модулю, установленному в компоненте приложения:

@Module(subcomponents = {ToastMakerSubComponent.class})
public abstract class ApplicationModule {

    private Context context;

    public ApplicationModule(Context context) {
        this.context = context;
    }

    @Provides
    @Singleton
    SharedPreferences provideSharedPreferences() {
        System.out.println("ApplicationModule context: " + context);
        return context.getSharedPreferences("PrefName", Context.MODE_PRIVATE);
    }

    @Binds
    @IntoMap
    @ActivityKey(MainActivity.class)
    abstract AndroidInjector.Factory<? extends Activity> bindMainActivityFactory(ToastMakerSubComponent.Builder builder);
}

Пусть каркасные классы расширяют Dagger* коллеги или реализовать Has*Injector интерфейсы, если вы не можете использовать наследование

public class MyApplication extends DaggerApplication {

    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        return DaggerApplicationComponent.create();
    }
}

public class MainActivity extends DaggerAppCompatActivity {

    @Inject
    SharedPreferences sharedPreferences;

    @Inject
    ToastMaker toastMaker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        toastMaker.showToast("sharedPreferences " + sharedPreferences);
    }
}
Другие вопросы по тегам