Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Touching motif - DI library for Android and Java applications

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. uber/motif
    @shaunkawano

    View Slide

  2. •DI library - simple API optimized for
    nested scopes
    •Generates Dagger code for actual
    DI
    •Under heavily development
    uber/motif

    View Slide

  3. View Slide

  4. Usage

    View Slide

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

    View Slide

  6. @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)
    }
    }

    View Slide

  7. @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)
    }
    }

    View Slide

  8. @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)
    }
    }

    View Slide

  9. View Slide

  10. View Slide

  11. 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 {
    }

    View Slide

  12. @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);
    }

    }

    View Slide

  13. View Slide

  14. public final class AppScopeImpl_Module_ApiFactory implements Factory {
    private final AppScopeImpl.Module module;
    private final Provider serviceProvider;
    public AppScopeImpl_Module_ApiFactory(
    AppScopeImpl.Module module, Provider serviceProvider) {
    this.module = module;
    this.serviceProvider = serviceProvider;
    }
    @Override
    public Api get() {
    return provideInstance(module, serviceProvider);
    }
    public static Api provideInstance(AppScopeImpl.Module module, Provider
    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 [email protected] @Provides
    method");
    }
    }

    View Slide

  15. It generates code similar to
    or the same as what dagger
    generates

    View Slide

  16. dagger & motif?

    View Slide

  17. # of concepts

    View Slide

  18. @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 {}
    }

    View Slide

  19. @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

    View Slide

  20. @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);
    }
    }
    }

    View Slide

  21. @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)

    View Slide

  22. •dagger
    •Fully customizable
    •Required to understand its concepts
    •Code readability concern
    •motif
    •Less customizable
    •Less concepts
    •More readable
    Philosophy

    View Slide

  23. @Expose

    View Slide

  24. @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)
    }
    }

    View Slide

  25. @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)
    }
    }

    View Slide

  26. @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)
    }
    }

    View Slide

  27. @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)
    }
    }

    View Slide

  28. View Slide

  29. @Expose

    View Slide

  30. @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)
    }
    }

    View Slide

  31. @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)
    }
    }

    View Slide

  32. Summary

    View Slide

  33. •DI library
    •Clearly different from Dagger
    •Under heavily development
    •Read and understand its philosophy
    before choosing to use it or not
    uber/motif

    View Slide

  34. Uber/Motif
    @shaunkawano
    Thank you!

    View Slide