如果没有@Provides注释的方法,则无法提供 Dagger2.11



我正在尝试理解Dagger 2.11中包含的dagger.android框架。我编写了一个示例代码,用于实现一些范围、@Singleton、@ActivityScope和@FragmentScope。

我的活动有一个片段,片段有一个玩具对象。我希望主片段属于活动范围,玩具对象属于片段范围。

但是我有一个错误,你能帮我吗?问题出在哪里?:

错误:(22, 8( 错误: [dagger.android.AndroidInjector.inject(T(] com.example.user.daggerapplication4.Models.Toy 無法提供 没有@Provides注释的方法。 com.example.user.daggerapplication4.Models.Toy 被注射在 com.example.user.daggerapplication4.ui.MainFragment.toy com.example.user.daggerapplication4.ui.MainFragment is 注入于 com.example.user.daggerapplication4.ui.MainActivity.injectedFragment com.example.user.daggerapplication4.ui.MainActivity is 注入于 dagger.android.AndroidInjector.inject(arg0( 具有匹配的绑定 组件中存在键: com.example.user.daggerapplication4.ui.MainActivityModule_BindMainFragment.主片段子组件

应用组件和模块:

@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();
}

范围:

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface FragmentScoped {}
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScoped {}

活动模块和片段模块

@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";
}
}

代码中有一些错误需要修复,以便编译项目。但首先,高效 Dagger 的经验法则 - 始终更喜欢使用抽象@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);
}

如果你有其他类来实现你想要注入的玩具接口,你必须使用限定符(@Named注释(来告诉 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并实现一些方法。我有一个完整的工作示例,您可以查看: https://github.com/Nimrodda/dagger-androidinjector 这是我写的一篇关于Dagger Android注入的文章的源代码 https://android.jlelse.eu/android-and-dagger-2-10-androidinjector-5e9c523679a3 我强烈建议您查看一下以更好地了解。

相关内容

最新更新