Reprository:https://github.com/googlesamples/android-architecture
Branch - todo-mvp-dagger
发现使用contructorinjection注入TaskFragment
例如: 在TasksModule中,我想为任务片段添加另一个模块,如下面的TaskFragment中的字段注入
@Module
class TasksModule{
@Fragmentscoped
@contributesandroidinjector(modules = AnotherModule.class)
abstract TasksFragment tasksFragment();
}
@Module
public class AnotherModule {
@Provides
@FragmentScoped
static Calendar getCalendar() {
return Calendar.getInstance();
}
}
@activityscoped
public class TasksFragment extends DaggerFragment implements TasksContract.View {
@Inject
Calendar calendar;//Field injection
@Inject
TasksFragment(){
}
}
活动:
public class TasksActivity extends DaggerAppCompatActivity {
@Inject
Lazy<TasksFragment> taskFragmentProvider;
....
}
我收到的错误是:
Error:(34, 8) error: [dagger.android.AndroidInjector.inject(T)] java.util.Calendar cannot be provided without an @Provides- or @Produces-annotated method.
java.util.Calendar is injected at
com.example.android.architecture.blueprints.todoapp.tasks.TasksFragment.calendar
dagger.Lazy<com.example.android.architecture.blueprints.todoapp.tasks.TasksFragment> is injected at
com.example.android.architecture.blueprints.todoapp.tasks.TasksActivity.taskFragmentProvider
com.example.android.architecture.blueprints.todoapp.tasks.TasksActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
A binding with matching key exists in component: com.example.android.architecture.blueprints.todoapp.tasks.TasksModule_TasksFragment.TasksFragmentSubcomponent
我在这里错过任何有关注射的内容吗?
答案 0 :(得分:2)
要直接回答您的问题,您显然正在尝试从ActivityComponent中实例化您的TasksFragment。但是,您已在@ragrag.Sandped范围内将日历绑定在dagger.android为您创建的特定于片段的子组件中。这意味着Calendar只能从Fragment(以及Fragment访问的其他对象)中获取,而不能从您的Activity中获取。
如果你想要正确的范围和注入组件,你可以使用Fragment的组件,它有一个生成的名称,没有片段构造方法:它的设计不是为了调用它方式。
答案很简单:不要依赖构造函数注入。你应该在你的片段上调用new
,因为这是Android的作用; you are required to have a public parameterless constructor专门用于此目的,Android不会在构建时注入您的Fragment。虽然这里没有关于构造函数注入和字段注入的任何特殊Dagger规则,但这是Android系统的约束以及为您重新创建Fragment实例的必要能力。
相反,通过扩展DaggerFragment,你是instructing Dagger to inject your Fragment in its onAttach
method,这是正确的方法,以及dagger.android的设计方式。如果您要先手动或自动注入Fragment,那么当附加Fragment时,这些@Inject字段将被替换并重新注入...并且您的Fragment会有不同的行为,具体取决于Android是否自动为您创建对象,或者你是否自己这样做。
其他说明:
@Inject Lazy<TasksFragment> taskFragmentProvider
称为提供者:与普通Provider
不同,Lazy
将始终返回相同的实例,即使该对象是无范围的。< / LI>
onAttach
方法,您可以使用这些Bundle参数对注入的对象具有完全访问权。