Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
498 views
in Technique[技术] by (71.8m points)

android - cannot be provided without an @Inject constructor or from an @Provides-annotated method

I am using Android Dagger2 but I am getting the error below.

My AppModule class is:

@Module
public class AppModule {
    @Provides
    public DownloadFilePresenterImp provideDownloadfilePresenterImp(DownloadFileView downloadFileView) {
        return new DownloadFilePresenterImp(downloadFileView);
    }
}

My AppComponent interface is:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(DownloadFileView target);
}

My DaggerInject class

public class DaggerInjector {
    private static AppComponent mAppComponent = DaggerAppComponent
            .builder()
            .appModule(new AppModule())
            .build();

    public static AppComponent getAppComponent() {
        return mAppComponent;
    }
}

I am trying to inject into my Fragment (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;
}

And my DownloadFilePresenterImp constructor part

public class DownloadFilePresenterImp implements DownloadFilePresenterContact {
    public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
        mDownloadFileContract = downloadFileView;
    }
}

This is the error I am getting:

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)

Many thanks for any suggestions,

question from:https://stackoverflow.com/questions/37434657/cannot-be-provided-without-an-inject-constructor-or-from-an-provides-annotated

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Ok...this should work

@Module
public class AppModule {
    @Provides
    public DownloadFilePresenterImp provideDownloadfilePresenterImp() {
        return new DownloadFilePresenterImp();
    }
}

and

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) {
                [...]
            }
        }
    }
}

Basically, all objects provided by the graph (the component) must be built with objects belonging or built by the graph itself. So I removed the DownloadFilePresenterImp(DownloadFileView downloadFileView) constructor that is going to cause a leak and replaced it with a setter that creates a WeakReference to the View.

EDIT

If you want to inject an object that you build at runtime, the only way to go is to pass that object to the AppComponent. In your case it could be:

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

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...