Android 如果没有@Provides注释的方法,则无法提供Dagger2.11
我试图理解dagger 2.11中包含的dagger.android框架。我编写了一个示例代码,实现了一些作用域、@Singleton、@ActivityScope和@FragmentScope 我的活动有一个片段,片段有一个玩具对象。我希望MainFragment属于活动范围,Toy对象属于Fragment范围 但是我有个错误,你能帮我吗?有什么问题吗 错误:(22,8)错误:[dagger.android.android注射器.inject(T)] 无法提供com.example.user.daggerapplication4.Models.Toy 如果没有@,则提供带注释的方法。 com.example.user.daggerapplication4.Models.Toy在 com.example.user.daggerapplication4.ui.MainFragment.toy com.example.user.daggerapplication4.ui.main片段在 com.example.user.daggerapplication4.ui.MainActivity.injectedFragment com.example.user.daggerapplication4.ui.main活动在 dagger.android.androidjector.inject(arg0)一个匹配的绑定 组件中存在密钥: com.example.user.daggerapplication4.ui.MainActivityModule_BindMainFragment.MainFragmentSubcomponent 应用程序组件和模块:Android 如果没有@Provides注释的方法,则无法提供Dagger2.11,android,dagger,Android,Dagger,我试图理解dagger 2.11中包含的dagger.android框架。我编写了一个示例代码,实现了一些作用域、@Singleton、@ActivityScope和@FragmentScope 我的活动有一个片段,片段有一个玩具对象。我希望MainFragment属于活动范围,Toy对象属于Fragment范围 但是我有个错误,你能帮我吗?有什么问题吗 错误:(22,8)错误:[dagger.android.android注射器.inject(T)] 无法提供com.example.user.
@Singleton
@Component(modules = {
AndroidInjectionModule.class,
AppModule.class,
ActivityBuilder.class
})
public interface AppComponent extends AndroidInjector<DaggerSample4Application> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<DaggerSample4Application> {}
}
@Module
public class AppModule {
}
@Module
public abstract class ActivityBuilder {
@ActivityScoped
@ContributesAndroidInjector(modules = MainActivityModule.class)
abstract MainActivity bindMainActivity();
}
ActivityModule和FragmentModule
@Module()
public abstract class MainActivityModule {
@FragmentScoped
@ContributesAndroidInjector(modules = MainFragmentModule.class)
abstract MainFragment bindMainFragment();
}
@Module
public class MainFragmentModule {
@Provides
@FragmentScoped
Toy provideToy()
{
return new Puzzle();
}
}
模型类:
public interface Toy {
public String play();
}
public class Puzzle implements Toy {
@Override
public String play() {
Log.v("DaggerSample","Play with Puzzle");
return "Play with Puzzle";
}
}
主活动和主片段
public class MainActivity extends DaggerAppCompatActivity {
@Inject
MainFragment injectedFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainFragment mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
// injectedFragment = new MainFragment();
if (mainFragment == null) {
mainFragment = injectedFragment;
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame, mainFragment);
transaction.commit();
}
}
}
public class MainFragment extends DaggerFragment {
private Button btnBuy;
private TextView textResult;
@Inject
Toy toy;
@Inject
public MainFragment()
{
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_main, container, false);
btnBuy = root.findViewById(R.id.btnBuy);
textResult = root.findViewById(R.id.textRresult);
btnBuy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showMessage(toy.play());
}
});
return root;
}
public void showMessage(String message) {
textResult.setText(message);
}
}
如果您想研究代码,您可以使用这个访问,我认为在使用接口时最好使用@Binds。 尝试下面的方法
@Module
public class MainFragmentModule {
@FragmentScoped
@Binds
public abstract Toy bindToy(Puzzle puzzle);
}
public class Puzzle implements Toy {
@Inject
public Puzzle(){
}
@Override
public String play() {
Log.v("DaggerSample","Play with Puzzle");
return "Play with Puzzle";
}
}
为了使项目得以编译,代码中有一些错误需要修复。但首先,高效匕首的经验法则——总是喜欢使用抽象@Binds方法将模块作为抽象类,如果不可能,则使用静态@Provides方法。这意味着您需要使AppModule成为一个抽象类,否则您的项目将无法按照您在此处发布的代码进行编译 您的代码无法编译的主要原因是因为Puzzle没有用@Inject注释的构造函数:
public class Puzzle implements Toy {
@Inject // Add this
public Puzzle() {
}
@Override
public String play() {
Log.v("DaggerSample","Play with Puzzle");
return "Play with Puzzle";
}
}
接下来,您需要对此模块进行以下更改:
@Module
public class MainFragmentModule { // Make this class abstract
@Provides // Change this to @Binds instead
@FragmentScoped
Toy provideToy() // Change this method to look like this below method
{
return new Puzzle();
}
@Binds
@FragmentScoped
abstract Toy bindPuzzle(Puzzle puzzle);
}
若有其他类实现了要注入的Toy接口,那个么必须使用限定符(@Named annotation)来告诉Dagger要注入哪个实现
您不能将片段注入承载它的活动。相反,您必须创建片段并使用片段管理器添加它
public class MainActivity extends DaggerAppCompatActivity {
@Inject // Remove this
MainFragment injectedFragment; // And this if you don't use this field
不能用@Inject注释片段构造函数。Fragment是一个Android组件,不能通过构造函数注入来注入Android组件。注入Android组件的唯一方法是通过成员注入,如果您的片段继承自DaggerFragment,那么这已经为您完成了。请注意,如果您使用的是支持库片段,请确保使用来自支持包的DaggerFragment变体
您还没有包含DaggerSample4Application代码,因此我无法判断您是否在那里做了错误的事情,但主要的一点是,该类需要扩展DaggerApplication并实现一些方法。我有一个完整的工作示例,您可以查看:
这是我写的一篇关于Dagger Android注入的文章的源代码
我强烈建议您查看它以获得更好的理解。似乎您正在尝试使用activitycomponent注入片段?是的,我正在尝试按MainActivitySubComponent注入MainFragment,按MainFragmentSubComponent注入玩具模型。它们有自己的作用域。请从片段构造函数中删除
@Inject
。Dagger将在创建片段后尝试注入字段,所有这些字段都来自ActivityComponent,因此是您的错误。如果我从MainActivity的构造函数和injectedFragment字段中删除@InjectAnnatation,我建议您创建不带Dagger的片段。成功了。这是否意味着,无法在活动范围上注入片段,同时在片段范围上注入字段?不能直接注入。我还没有这样做,但你必须使用它自己的子组件创建片段,并以某种方式将此工厂包含在你的活动组件中。我尝试使用@Binds注释,但我遇到了相同的异常。你在拼图构造函数中给@inject了吗?是的,我给了。但结果是一样的:(你们可以用它来访问代码,难道它不需要把MainFragmentModule设置为'abstract')吗?否则我相信它会给出编译时错误。
public class MainActivity extends DaggerAppCompatActivity {
@Inject // Remove this
MainFragment injectedFragment; // And this if you don't use this field