Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/188.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如果没有@Provides注释的方法,则无法提供Dagger2.11_Android_Dagger - Fatal编程技术网

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

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.

我试图理解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

应用程序组件和模块:

@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