2017-07-04 34 views
5

This is a Canonical Question because this is a common error with Dagger 2.如何解決Dagger 2錯誤'...無法提供[...]'?

If your question was flagged as a duplicate please read this post carefully and make sure to understand what this error means and why it occured. If this post does not work for you make sure to include where and how you provide the mentioned classes and include the full error message in your question like the one here.

我試圖用一個依賴與匕首2,但我收到以下錯誤,當我嘗試編譯我的項目:

error: com.example.MyDependency cannot be provided without an @Inject constructor or from an @Provides-annotated method.

com.example.MyDependency is provided at
com.example.MyComponent.myDependency()

這是什麼意思?如何解決呢?

我有一個組件,並試圖提供一個依賴項。我的基本設置是這樣的:

// this is the dependency I try to use 
class MyDependency {} 

@Component 
interface MyComponent { 
    // I want to make it accessible to be used with my component 
    MyDependency myDependency(); 
} 

回答

14

TL;博士你忘了或者添加@Inject到您的構造函數,以便匕首可以使用構造器注入到提供對象,或者你需要一些方法在一個你創建或綁定對象的模塊。


這是怎麼回事?

仔細看看錯誤消息:它聲明您嘗試請求依賴項,但匕首無法提供或創建它。它根本不知道如何去做,因爲如果沒有@Inject構造函數或者來自@Provision-Annotated方法,就不能提供

仔細看錯誤消息顯示類(一)您試圖提供和組件(B)需要它。

com.example.MyDependency (a) is provided at
com.example.MyComponent.myDependency() (b)

你必須確保(B)可以創建或提供(一),以解決您的問題。

它看起來有點複雜,如果你試圖在別的地方注入你的依賴關係,但你仍然可以看到在這種情況下構造函數注入缺少依賴關係的事件—的完整堆棧。你試圖提供的類(a)和Dagger試圖注入的位置(b)。它也告訴你哪個依賴類創建的地方是(c),並且再次提供了組件(d),它提供的失敗(a)

com.example.MyDependency cannot be provided without an @Inject constructor or from an @Provides-annotated method.
com.example.MyDependency (a) is injected at
com.example.DependentClass.(dependency) (b)
com.example.DependentClass is provided at (c)
com.example.MyComponent.myDependency() (d)

同樣適用於這裏:確保(d)知道如何提供(一),你是好去。

我該如何解決這個問題?

看看上面的錯誤。確保你明白其中它發生和什麼你試圖注入。然後告訴Dagger如何提供你的對象。

的@Inject構造

由於錯誤狀態,您嘗試使用MyDependencyMyComponent不知道該怎麼做。如果我們看一下例子就變得很清楚,爲什麼:

class MyDependency {} 

類有沒有@Inject註釋構造!而且組件中沒有其他模塊,所以Dagger沒有什麼可以做的。

如果你想使用構造函數注入,你可以只需添加一個@Inject註釋構造函數並完成。 Dagger會看到這個構造函數並知道如何創建你的類。

class MyDependency { 
    @Inject 
    MyDependency() { /**/ } 
} 

這就是您在使用構造函數注入時必須要做的所有事情。

從@提供註解方法

錯誤信息指出第二個選項,它允許您提供一個對象,如果你不希望—或無法—使用構造函數注入做。您還可以@Provides帶註釋的方法添加到模塊並將此模塊添加到您的組件。

@Module 
class MyModule { 
    @Provides 
    MyDependency provideMyDependency() { 
     return new MyDependency(); 
    } 
} 

@Component(modules = MyModule.class) 
interface MyComponent { 
    MyDependency myDependency(); 
} 

這樣Dagger可以使用你的模塊來創建並提供依賴。它比使用構造函數注入要多一點樣板,但是對於需要進一步設置或者沒有註釋構造函數的所有東西,第三方庫,如Retrofit,OkHttp或Gson。


還有其他方法可以從組件中提供依賴關係。 A @SubComponent可以訪問其父項依賴項,並且組件依賴項可以將其某些依賴項公開給其依賴項組件。但是在某些時候,Dagger提供的一切都需要有一個@Inject構造函數或一個提供它的模塊。

但我確實加了MyDependency

密切關注細節。當您僅提供實現時,您可能正在使用接口,或者當Dagger僅知道子類時嘗試使用父類。
也許你添加了自定義@Qualifier或使用了@Named("typeA")。匕首這是一個完全不同的對象!仔細檢查你是否實際提供並請求相同的依賴關係。

讀取錯誤,並確保你要麼有一個@Inject註釋構造,具有@Provides方法提供某種類型,或者,做了父組件的模塊。

如果我想爲我的界面提供實現,該怎麼辦?

一個簡單的例子,如以下顯示如何一個類繼承了另一個問題:

class MyDependency extends MyBaseDependency { 
    @Inject MyDependency() { super(); } 
} 

這將通知匕首約MyDependency但不是MyBaseDependency

如果您有一個類實現接口或擴展超類,則必須聲明該類。如果您提供MyDependency這並不意味着Dagger可以提供MyBaseDependency。你可以使用@Binds告訴Dagger你的實現,並在需要超類的時候提供它。

@Module 
interface MyModule { 
    @Binds 
    MyBaseDependency provideMyBaseDependency(MyDependency implementation); 
} 
+4

寫得很好! –

+0

使用Binds設置接口的實現時,是否仍然需要爲接口創建@Provides方法來返回實現? – jonney

+0

@jonney不,你不需要額外的@ @提供。 '@ Binds'也將提供實現/接口。 –

相關問題