Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Parent service was bound before child in MultiKey.  #201

@novachevskyi

Description

@novachevskyi

I faced an issue when I was trying to setup MultiKey with child, when child's component should be inherited from MultiKey's component. In other words, child services are always created before parent MultiKey service.

Let me show an example. MultiKey declaration:

class ParentMultiKey implements MultiKey {
    @Override public List<Object> getKeys() {
        return Collections.singletonList(new ChildKey());
    }
}

ParentMultiKey's component:

@Component
interface ParentComponent {}

Child key declaration:

class ChildKey {}

ChildKey's component:

@Component(dependencies = ParentComponent.class)
interface ChildComponent {}

ServicesFactory implementation:

class SampleServicesFactory extends ServicesFactory {
    private static final String DAGGER_COMPONENT = "DAGGER_COMPONENT";
    private static Map<Class, Object> cachedComponents = new HashMap<>();

    @Override
    public void bindServices(@NonNull Services.Binder services) {
        Object key = services.getKey();

        if (key instanceof ParentMultiKey) {
            Object component = DaggerParentComponent.builder().build();

            cachedComponents.put(ParentComponent.class, component);
            services.bind(DAGGER_COMPONENT, component);
        } else if (key instanceof ChildKey) {
            Object component = DaggerChildComponent.builder()
                    .parentComponent((ParentComponent) cachedComponents.get(ParentComponent.class))
                    .build();

            cachedComponents.put(ChildComponent.class, component);
            services.bind(DAGGER_COMPONENT, component);
        }
    }
}

As you can see, my ChildKeyComponent is inherited from ParentMultiKeyComponent. At the moment of services setup, ChildKey's services would be created before ParentMultiKey's services.

The possible fix is to place KeyManager::ensureNode call before foreach within KeyManager::setUp method:

void setUp(Object key) {
    Services parent = managedServices.get(ROOT_KEY).services;
    if (key instanceof MultiKey) {
      ensureNode(parent, key).uses++;
      for (Object part : ((MultiKey) key).getKeys()) {
        setUp(part);
      }
    } else if (key instanceof TreeKey) {
      TreeKey treeKey = (TreeKey) key;
      final Object parentKey = treeKey.getParentKey();
      setUp(parentKey);
      parent = managedServices.get(parentKey).services;
      ensureNode(parent, key).uses++;
    } else {
      ensureNode(parent, key).uses++;
    }
  }

Please let me know if I'm missing something here or if some other solution should be applied to fix this issue. I will appreciate for your help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions