Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Provide a Context scope for @EBean #205

@pyricau

Description

@pyricau

This issue is based on feedback in #197, where a user wanted to shared a ViewHolder between various components tied to an Activity.

Currently, @EBean classes can have a default scope or a singleton scope. The default scope means a new instance is created for each injection, and the singleton scope means there's only one instance for the whole application life.

We need a Context scope for cases where two beans depends on the same bean and want to manipulate the same instance. The beans will have the same lifespan as the context instance.

They may be saved and reinjected in an activity when annotated with @NonConfigurationInstance.

@EActivity
public class MyActivity extends Activity {

  @Bean
  BeanA beanA;

  @Bean
  BeanB beanB;
}

BeanA also references BeanB, and we want the same BeanB instance to be in BeanA and MyActivity

@EBean
public class BeanA {
  @Bean
  BeanB beanB;
}

So we use the Context scope :

@EBean(scope = Scopes.Context)
public class BeanB {
}

How do we implement that ?

We'll let each generated activity (or service, or application) implement an interface with the following contract (may change):

public interface BeanHolder {
  // May return null if the bean hasn't been created yet
  <T> T getBean_(Class<T> key);
  <T> void putBean_(Class<T> key, T value);
}

The implementation should be along those lines:

public class MyActivity_ extends MyActivity implements BeanHolder {

  private final Map<Class<?>, Object> beans_ = new HashMap<Class<?>, Object>();

  public void <T> T getBean_(Class<T> key) {
    return (T) beans_.get(key);
  }

  public void <T> void putBean_(Class<T> key, T value) {
    beans_.put(key, value);
  }
}

And the build method for a bean with Context scope :

public class MyBean_ extends MyBean {

    public MyBean_ build(Context context) {
      if (context instanceof BeanHolder) {
         BeanHolder beanHolder = (BeanHolder) context;
         MyBean_ bean = beanHolder.getBean_(MyBean_.class);
        if (bean == null) {
          bean = new MyBean_(context);
          beanHolder.putBean_(bean);
        }
        return bean;
      } else {
        // TODO => what should we do ?
      }
    }
}

Notice that we handle the case where the given context is not a BeanHolder. This may happen when singletons depend on beans with context scope, or when singleton depends on beans with default scope which themselves depend on beans with context scope. In either cases, we know that our bean will have an "application" / "singleton" scope, because it now depends on the application context. So we should probably have a singleton like construct, and return the singleton reference in that case.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions