不能在没有 @Inject 构造函数或 @Provides 注释的方法的情况下提供
cannot be provided without an @Inject constructor or from an @Provides-annotated method
我正在使用 Android Dagger2,但出现以下错误。
我的 AppModule class 是:
@Module
public class AppModule {
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp(DownloadFileView downloadFileView) {
return new DownloadFilePresenterImp(downloadFileView);
}
}
我的 AppComponent 接口是:
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(DownloadFileView target);
}
我的 DaggerInject class
public class DaggerInjector {
private static AppComponent mAppComponent = DaggerAppComponent
.builder()
.appModule(new AppModule())
.build();
public static AppComponent getAppComponent() {
return mAppComponent;
}
}
我正在尝试注入我的片段 (DownloadFileView)
@Inject DownloadFilePresenterImp mDownloadFilePresenterImp;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.download_file_view, container, false);
/* Initialize presenter */
DaggerInjector.getAppComponent().inject(DownloadFileView.this);
/* Use mDownloadFilePresenterImp here */
return view;
}
还有我的 DownloadFilePresenterImp 构造函数部分
public class DownloadFilePresenterImp implements DownloadFilePresenterContact {
public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
mDownloadFileContract = downloadFileView;
}
}
这是我遇到的错误:
Error:(17, 10) error: com.sunsystem.downloadfilechatapp.downloader.DownloadFileView cannot be provided without an @Inject constructor or from an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.
com.sunsystem.downloadfilechatapp.downloader.DownloadFileView is injected at
com.sunsystem.downloadfilechatapp.downloader.dagger.AppModule.provideDownloadfilePresenterImp(downloadFileView)
com.sunsystem.downloadfilechatapp.downloader.DownloadFilePresenterImp is injected at
com.sunsystem.downloadfilechatapp.downloader.DownloadFileView.mDownloadFilePresenterImp
com.sunsystem.downloadfilechatapp.downloader.DownloadFileView is injected at
com.sunsystem.downloadfilechatapp.downloader.dagger.AppComponent.inject(target)
非常感谢您的任何建议,
好的...这应该有效
@Module
public class AppModule {
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp() {
return new DownloadFilePresenterImp();
}
}
和
public class DownloadFilePresenterImp implements DownloadFilePresenterContact {
private WeakReference<DownloadFileView> weak;
public DownloadFilePresenterImp() {
}
public void setDownloadFileView(DownloadFileView view) {
weak = new WeakReference<>(view);
}
public void doSomething() {
if (weak != null) {
DownloadFileView view = weak.get();
if (view != null) {
[...]
}
}
}
}
基本上,图(组件)提供的所有对象都必须使用属于图本身或由图本身构建的对象来构建。因此,我删除了将导致泄漏的 DownloadFilePresenterImp(DownloadFileView downloadFileView)
构造函数,并将其替换为 setter 以创建对视图的 WeakReference。
编辑
如果你想注入一个你在运行时构建的对象,唯一的方法就是将该对象传递给 AppComponent。在您的情况下,它可能是:
AppComponent.java
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(DownloadFileView target);
}
AppModule.java
@Module
public class AppModule {
private final DownloadFileView downloadFileView;
public AppModule(DownloadFileView downloadFileView) {
this.downloadFileView = downloadFileView;
}
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp() {
return new DownloadFilePresenterImp(downloadFileView);
}
}
DownloadFilePresenterImp.java
public class DownloadFilePresenterImp {
private final DownloadFileView downloadFileView;
public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
this.downloadFileView = downloadFileView;
}
}
DownloadFileView.java
public class DownloadFileView extends Fragment {
private AppComponent mAppComponent;
@Inject
DownloadFilePresenterImp impl;
public DownloadFileView() {
// Required empty public constructor
mAppComponent = DaggerAppComponent
.builder()
.appModule(new AppModule(this))
.build();
mAppComponent.inject(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_download_file_view, container, false);
}
}
该错误仅说明 dagger 无法提供所述依赖项。您将不得不以某种方式将它添加到您的组件中——因为它是一个 Fragment
——你将不得不使用一个 @Module
.
我假设您的 AppComponent
是由您的 Application
在开始时创建的。您的 AppComponent
的生命周期比您的活动和片段生命周期都长。因此,它不知道如何提供 activity 或您的情况下的片段是合理的。
- 你的
DownloadFilePresenterImp
取决于你的 DownloadFileView
。
- 您想将
DownloadFilePresenterImp
注入您的 DownloadFileView
- 要注入视图和演示者,您正在使用您的
AppComponent
,它对 activity 一无所知,显然对片段一无所知。它具有不同的范围和生命周期。
为了不进一步引起混淆,我将谈论片段,因为它们和活动生命周期是您必须牢记的。您可以只对模块使用 DownloadFileView
,但是这些长名称会让人感到困惑。
要提供一个片段或activity你有使用一个模块。例如
@Module FragmentModule {
Fragment mFragment;
FragmentModule(Fragment fragment) { mFragment = fragment; }
@Provides Fragment provideFragment() { return mFragment; }
// here you could also provide your view implementation...
@Provides DownloadFileView provideDownloadFileView() {
return (DownloadFileView) mFragment;
}
}
由于该模块只应与片段生命周期一起存在,因此您必须使用子组件或依赖于您的AppComponent
.[=28=的组件]
@Component(dependencies=AppComponent.class, modules=FragmentModule.class)
interface FragmentComponent {
// inject your fragment
void inject(DownloadFileView fragment);
}
在您的片段中,您必须正确地创建您的组件...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.download_file_view, container, false);
// properly create a component that knows about the fragment
DaggerFragmentComponent.builder()
.appComponent(DaggerInjector.getAppComponent())
.fragmentModule(new FragmentModule(this))
.build()
.inject(DownloadFileView.this);
return view;
}
另外,我强烈推荐看看并使用构造函数注入
public class DownloadFilePresenterImp implements DownloadFilePresenterContact {
@Inject
public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
mDownloadFileContract = downloadFileView;
}
}
或者,如果您喜欢冗余代码,您可以将 provideDownloadfilePresenterImp(View)
方法移动到 FragmentModule
以获得相同的效果。
完成。
我强烈建议您查看拖动器的完整实现:
https://github.com/Spentas/securechat/blob/master/app/src/main/java/com/spentas/javad/securechat/app/AppComponent.java
或关注以下内容:
在您的 AppModule 中:
@Singleton
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp(DownloadFileView downloadFileView) {
return new DownloadFilePresenterImp(downloadFileView);
}
您的 AppComponent:
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(DownloadFileView target);
}
然后你需要在你的应用程序中初始化你的匕首 Class :
public class App extends Application {
private AppComponent component;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
component = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
}
public AppComponent getComponent(){
return component;
}
在任何你想使用的地方:
((App) App.getContext()).getComponent().inject(this);
对我来说,问题是另一个组件有一个未使用的注入方法,其输入参数与 class 相同。删除了注入方法并编译。
就我而言,我在 Kotlin 中有一个演示者 class,同时使用 Dagger2。我忘了
@Inject constructor
作为演示者的构造函数。
匕首错误不是很有用
就我而言,我在主 :app
模块和其他模块之间使用了不匹配的版本。确保您使用的是正确的版本,并且它们在模块之间是相同的。
作为永久修复,在我的 android 级别 build.gradle
中,我有以下内容:
buildscript {
ext.dagger_version = "2.30.1"
}
我所有的模块 build.gradle
文件都引用相同的版本:
// Dependency Injection
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
我正在使用 Android Dagger2,但出现以下错误。
我的 AppModule class 是:
@Module
public class AppModule {
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp(DownloadFileView downloadFileView) {
return new DownloadFilePresenterImp(downloadFileView);
}
}
我的 AppComponent 接口是:
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(DownloadFileView target);
}
我的 DaggerInject class
public class DaggerInjector {
private static AppComponent mAppComponent = DaggerAppComponent
.builder()
.appModule(new AppModule())
.build();
public static AppComponent getAppComponent() {
return mAppComponent;
}
}
我正在尝试注入我的片段 (DownloadFileView)
@Inject DownloadFilePresenterImp mDownloadFilePresenterImp;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.download_file_view, container, false);
/* Initialize presenter */
DaggerInjector.getAppComponent().inject(DownloadFileView.this);
/* Use mDownloadFilePresenterImp here */
return view;
}
还有我的 DownloadFilePresenterImp 构造函数部分
public class DownloadFilePresenterImp implements DownloadFilePresenterContact {
public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
mDownloadFileContract = downloadFileView;
}
}
这是我遇到的错误:
Error:(17, 10) error: com.sunsystem.downloadfilechatapp.downloader.DownloadFileView cannot be provided without an @Inject constructor or from an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.
com.sunsystem.downloadfilechatapp.downloader.DownloadFileView is injected at
com.sunsystem.downloadfilechatapp.downloader.dagger.AppModule.provideDownloadfilePresenterImp(downloadFileView)
com.sunsystem.downloadfilechatapp.downloader.DownloadFilePresenterImp is injected at
com.sunsystem.downloadfilechatapp.downloader.DownloadFileView.mDownloadFilePresenterImp
com.sunsystem.downloadfilechatapp.downloader.DownloadFileView is injected at
com.sunsystem.downloadfilechatapp.downloader.dagger.AppComponent.inject(target)
非常感谢您的任何建议,
好的...这应该有效
@Module
public class AppModule {
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp() {
return new DownloadFilePresenterImp();
}
}
和
public class DownloadFilePresenterImp implements DownloadFilePresenterContact {
private WeakReference<DownloadFileView> weak;
public DownloadFilePresenterImp() {
}
public void setDownloadFileView(DownloadFileView view) {
weak = new WeakReference<>(view);
}
public void doSomething() {
if (weak != null) {
DownloadFileView view = weak.get();
if (view != null) {
[...]
}
}
}
}
基本上,图(组件)提供的所有对象都必须使用属于图本身或由图本身构建的对象来构建。因此,我删除了将导致泄漏的 DownloadFilePresenterImp(DownloadFileView downloadFileView)
构造函数,并将其替换为 setter 以创建对视图的 WeakReference。
编辑
如果你想注入一个你在运行时构建的对象,唯一的方法就是将该对象传递给 AppComponent。在您的情况下,它可能是:
AppComponent.java
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(DownloadFileView target);
}
AppModule.java
@Module
public class AppModule {
private final DownloadFileView downloadFileView;
public AppModule(DownloadFileView downloadFileView) {
this.downloadFileView = downloadFileView;
}
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp() {
return new DownloadFilePresenterImp(downloadFileView);
}
}
DownloadFilePresenterImp.java
public class DownloadFilePresenterImp {
private final DownloadFileView downloadFileView;
public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
this.downloadFileView = downloadFileView;
}
}
DownloadFileView.java
public class DownloadFileView extends Fragment {
private AppComponent mAppComponent;
@Inject
DownloadFilePresenterImp impl;
public DownloadFileView() {
// Required empty public constructor
mAppComponent = DaggerAppComponent
.builder()
.appModule(new AppModule(this))
.build();
mAppComponent.inject(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_download_file_view, container, false);
}
}
该错误仅说明 dagger 无法提供所述依赖项。您将不得不以某种方式将它添加到您的组件中——因为它是一个 Fragment
——你将不得不使用一个 @Module
.
我假设您的 AppComponent
是由您的 Application
在开始时创建的。您的 AppComponent
的生命周期比您的活动和片段生命周期都长。因此,它不知道如何提供 activity 或您的情况下的片段是合理的。
- 你的
DownloadFilePresenterImp
取决于你的DownloadFileView
。 - 您想将
DownloadFilePresenterImp
注入您的DownloadFileView
- 要注入视图和演示者,您正在使用您的
AppComponent
,它对 activity 一无所知,显然对片段一无所知。它具有不同的范围和生命周期。
为了不进一步引起混淆,我将谈论片段,因为它们和活动生命周期是您必须牢记的。您可以只对模块使用 DownloadFileView
,但是这些长名称会让人感到困惑。
要提供一个片段或activity你有使用一个模块。例如
@Module FragmentModule {
Fragment mFragment;
FragmentModule(Fragment fragment) { mFragment = fragment; }
@Provides Fragment provideFragment() { return mFragment; }
// here you could also provide your view implementation...
@Provides DownloadFileView provideDownloadFileView() {
return (DownloadFileView) mFragment;
}
}
由于该模块只应与片段生命周期一起存在,因此您必须使用子组件或依赖于您的AppComponent
.[=28=的组件]
@Component(dependencies=AppComponent.class, modules=FragmentModule.class)
interface FragmentComponent {
// inject your fragment
void inject(DownloadFileView fragment);
}
在您的片段中,您必须正确地创建您的组件...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.download_file_view, container, false);
// properly create a component that knows about the fragment
DaggerFragmentComponent.builder()
.appComponent(DaggerInjector.getAppComponent())
.fragmentModule(new FragmentModule(this))
.build()
.inject(DownloadFileView.this);
return view;
}
另外,我强烈推荐看看并使用构造函数注入
public class DownloadFilePresenterImp implements DownloadFilePresenterContact {
@Inject
public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
mDownloadFileContract = downloadFileView;
}
}
或者,如果您喜欢冗余代码,您可以将 provideDownloadfilePresenterImp(View)
方法移动到 FragmentModule
以获得相同的效果。
完成。
我强烈建议您查看拖动器的完整实现: https://github.com/Spentas/securechat/blob/master/app/src/main/java/com/spentas/javad/securechat/app/AppComponent.java
或关注以下内容:
在您的 AppModule 中:
@Singleton
@Provides
public DownloadFilePresenterImp provideDownloadfilePresenterImp(DownloadFileView downloadFileView) {
return new DownloadFilePresenterImp(downloadFileView);
}
您的 AppComponent:
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(DownloadFileView target);
}
然后你需要在你的应用程序中初始化你的匕首 Class :
public class App extends Application {
private AppComponent component;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
component = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
}
public AppComponent getComponent(){
return component;
}
在任何你想使用的地方:
((App) App.getContext()).getComponent().inject(this);
对我来说,问题是另一个组件有一个未使用的注入方法,其输入参数与 class 相同。删除了注入方法并编译。
就我而言,我在 Kotlin 中有一个演示者 class,同时使用 Dagger2。我忘了
@Inject constructor
作为演示者的构造函数。
匕首错误不是很有用
就我而言,我在主 :app
模块和其他模块之间使用了不匹配的版本。确保您使用的是正确的版本,并且它们在模块之间是相同的。
作为永久修复,在我的 android 级别 build.gradle
中,我有以下内容:
buildscript {
ext.dagger_version = "2.30.1"
}
我所有的模块 build.gradle
文件都引用相同的版本:
// Dependency Injection
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"