When should I use Factory instead of Provider

2019-04-28 18:11发布

The Dagger documentation shows using a Provider<Filter> to get Filter instances, which appears to make perfect sense.

I am writing a ListAdapter which instantiates Views, which I'd like Dagger to inject. I'm tempted to inject a Provider<ViewType> into my ListAdapter, and call mViewProvider.get() to instantiate views.

However, the Dagger documentation says:

Injecting Provider<T> has the possibility of creating confusing code, and may be a design smell of mis-scoped or mis-structured objects in your graph. Often you will want to use a Factory<T> or a Lazy<T> or re-organize the lifetimes and structure of your code to be able to just inject a T

I can see how I could use a Factory, in a similar manner to that required when using assisted injection.

But what advantage would using my own Factory<T> have over using Dagger's Provider<T>, given I'd have to write the former myself?

1条回答
趁早两清
2楼-- · 2019-04-28 18:44

Provider<T> has a very concrete meaning in the system. It is a delegated constructor of a Graph-managed object. Provider<T> has specific guarantees/behaviour and I generally recommend against injecting Provider<T> unless you are supporting some legacy situation that requires it.

Factory<T> is an example - FooFactory is more accurate, because the intent of this is that you not use hand-rolled factories, but instead use something like AutoFactory (http://github.com/google/auto) to generate factories that create objects. Then you don't have to write your own, but AutoFactory was not yet built when these docs were written.

Ultimately the reason is primarily code-clarity and long-term maintenance. Using dagger's instance management as a de-facto Factory of instances is possible, but limited, as it can only work with instances that have injected dependencies. Call-stack dependencies cannot be supported without adding another scope, or graph layer. That fact has, in Guice, often caused people to use extra scopes to shoe-horn call-stack dependencies into object instance (provision) dependencies by playing games with custom scopes and complexifying their object graph and layering just to get some free code.

It was to solve this that (in guice) Assisted-Injection and (in Dagger) AutoFactory was created - so you could do the more semantically clearer thing that didn't depend on framework internals, but get it automatically done for you.

Not using Provider<T> is an opinion. You are free to do so if you wish, but it is not recommended practice. Instead we recommend a solution like AutoFactory to get better named types, with clearer meaning in your system, that can support more flexible handling of call-stack state.

查看更多
登录 后发表回答