Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Touching motif - DI library for Android and Jav...

Touching motif - DI library for Android and Java applications

I have talked about uber/motif library which provides simple API for dependency injection at potatotips#54.

uber/motif: A simple DI API for Android / Java
https://github.com/uber/motif

Shohei Kawano

August 23, 2018
Tweet

More Decks by Shohei Kawano

Other Decks in Technology

Transcript

  1. •DI library - simple API optimized for nested scopes •Generates

    Dagger code for actual DI •Under heavily development uber/motif
  2. @motif.Scope interface AppScope { @motif.Objects abstract class Objects { fun

    okHttpClient(): OkHttpClient = 
 OkHttpClient.Builder().build() fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl("") .addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync()) .build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  3. @motif.Scope interface AppScope { @motif.Objects abstract class Objects { fun

    okHttpClient(): OkHttpClient = 
 OkHttpClient.Builder().build() fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl("") .addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync()) .build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  4. @motif.Scope interface AppScope { @motif.Objects abstract class Objects { fun

    okHttpClient(): OkHttpClient = 
 OkHttpClient.Builder().build() fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl("") .addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync()) .build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  5. @motif.Scope interface AppScope { @motif.Objects abstract class Objects { fun

    okHttpClient(): OkHttpClient = 
 OkHttpClient.Builder().build() fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl("") .addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync()) .build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  6. public class AppScopeImpl implements AppScope { private final Component component;

    public AppScopeImpl(Dependencies dependencies) { this.component = DaggerAppScopeImpl_Component.builder() .dependencies(dependencies) .module(new Module()) .build(); } public AppScopeImpl() { this(new Dependencies() {}); } public interface Dependencies { } @DaggerScope @dagger.Component( dependencies = Dependencies.class, modules = Module.class ) interface Component { } private static class Objects extends AppScope.Objects { } …
  7. @dagger.Module class Module { private final AppScope.Objects objects = new

    Objects(); @Provides AppScope appScope() { return AppScopeImpl.this; } @Provides @DaggerScope OkHttpClient okHttpClient() { return objects.okHttpClient(); } @Provides @DaggerScope Retrofit retrofit(OkHttpClient okHttpClient) { return objects.retrofit(okHttpClient); } @Provides @DaggerScope Service service(Retrofit retrofit) { return objects.service(retrofit); } … }
  8. public final class AppScopeImpl_Module_ApiFactory implements Factory<Api> { private final AppScopeImpl.Module

    module; private final Provider<Service> serviceProvider; public AppScopeImpl_Module_ApiFactory( AppScopeImpl.Module module, Provider<Service> serviceProvider) { this.module = module; this.serviceProvider = serviceProvider; } @Override public Api get() { return provideInstance(module, serviceProvider); } public static Api provideInstance(AppScopeImpl.Module module, Provider<Service> serviceProvider) { return proxyApi(module, serviceProvider.get()); } … public static Api proxyApi(AppScopeImpl.Module instance, Service service) { return Preconditions.checkNotNull( instance.api(service), "Cannot return null from a non-@Nullable @Provides method"); } }
  9. @RootComponent.Scope @Component(modules = RootComponent.Module.class) public interface RootComponent { RootController controller();

    LoggedInComponent.Builder loggedIn(); @dagger.Component.Builder interface Builder { @BindsInstance Builder viewGroup(@Root ViewGroup parent); RootComponent build(); } @dagger.Module abstract class Module { @Scope @Provides static RootView view(@Root ViewGroup parent) { return RootView.create(parent); } } @javax.inject.Scope @interface Scope {} @Qualifier @interface Root {} }
  10. @RootComponent.Scope @Component(modules = RootComponent.Module.class) public interface RootComponent { RootController controller();

    LoggedInComponent.Builder loggedIn(); @dagger.Component.Builder interface Builder { @BindsInstance Builder viewGroup(@Root ViewGroup parent); RootComponent build(); } @dagger.Module abstract class Module { @Scope @Provides static RootView view(@Root ViewGroup parent) { return RootView.create(parent); } } @javax.inject.Scope @interface Scope {} @Qualifier @interface Root {} } •@Scope •@Component / @Subcomponent •@Component.Buidler / @Subcomponent.Builder •@Qualifier •@BindsInstance •@Module •@Provides •abstract @Modules •static @Provides •Component provision method •Component factory method •Constructor injection
  11. @Scope public interface RootScope { RootController controller(); LoggedInScope loggedIn(ViewGroup parentViewGroup);

    @motif.Objects abstract class Objects { abstract RootController controller(); RootView view(ViewGroup viewGroup) { return RootView.create(viewGroup); } } }
  12. @Scope public interface RootScope { RootController controller(); LoggedInScope loggedIn(ViewGroup parentViewGroup);

    @motif.Objects abstract class Objects { abstract RootController controller(); RootView view(ViewGroup viewGroup) { return RootView.create(viewGroup); } } } •@motif.Scope •@motif.Objects •Access method •Child method •Factory method (Basic) •Factory method (Constructor Injected)
  13. •dagger •Fully customizable •Required to understand its concepts •Code readability

    concern •motif •Less customizable •Less concepts •More readable Philosophy
  14. @motif.Scope interface ChildScope { @motif.Objects open class Objects { fun

    childService(retrofit: Retrofit): ChildService = retrofit.create(ChildService::class.java) fun childApi(childService: ChildService): ChildApi = ChildApiClient(childService) } }
  15. @motif.Scope interface ChildScope { @motif.Objects open class Objects { fun

    childService(retrofit: Retrofit): ChildService = retrofit.create(ChildService::class.java) fun childApi(childService: ChildService): ChildApi = ChildApiClient(childService) } }
  16. @motif.Scope interface AppScope { fun childScope(): ChildScope @motif.Objects open class

    Objects { fun okHttpClient(): OkHttpClient = OkHttpClient.Builder().build() fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl(“") .addCallAdapterFactory(RxJava2CallAdapterFactory .createAsync()).build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  17. @motif.Scope interface AppScope { fun childScope(): ChildScope @motif.Objects open class

    Objects { fun okHttpClient(): OkHttpClient = OkHttpClient.Builder().build() fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl(“") .addCallAdapterFactory(RxJava2CallAdapterFactory .createAsync()).build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  18. @motif.Scope interface AppScope { fun childScope(): ChildScope @motif.Objects open class

    Objects { fun okHttpClient(): OkHttpClient = OkHttpClient.Builder().build() fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl(“") .addCallAdapterFactory(RxJava2CallAdapterFactory .createAsync()) .build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  19. @motif.Scope interface AppScope { fun childScope(): ChildScope @motif.Objects open class

    Objects { fun okHttpClient(): OkHttpClient = OkHttpClient.Builder().build() @Expose fun retrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder().client(okHttpClient).baseUrl("") .addCallAdapterFactory(RxJava2CallAdapterFactory .createAsync()) .build() fun service(retrofit: Retrofit): Service = retrofit.create(Service::class.java) fun api(service: Service): Api = ApiClient(service) } }
  20. •DI library •Clearly different from Dagger •Under heavily development •Read

    and understand its philosophy before choosing to use it or not uber/motif