2016-02-23 185 views
3

我明白,用匕首2我不能注入基類,並期望它繼承到子類。但是爲什麼我不能在子類中調用注入,除非我明確指出該類的方法是inject匕首2注入子類

我試過以下這篇文章中的例子:Dagger 2: Even Sharper, Less Square。這個解決方案應該允許我在一個子類中調用注入,但是當我測試它時,我得到了一個NullPointerException用於我所有的@Inject目標。

public abstract class BaseFragment extends Fragment { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     injectComponent(MyApplication.getComponent()); 
    } 

    protected abstract void injectComponent(AppComponent component); 
} 

public class MyFragment extends BaseFragment { 

    @Inject MyDependency mDependency; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 
     mDependency.doSomething(); // NullPointerException 
     ... 
    } 

    ... 

    @Override 
    public void injectComponent(AppComponent component) { 
     component.inject(this); 
    } 
} 

是否有另一種方法注入到每個子類中,而無需爲每個類創建注入方法?或者這是Dagger 2的唯一方法嗎?如果是這樣的話,我最終會得到一個荒謬的長課程Component。隨着每一個ActivityFragment或其他各種輔助類的注射方法:

@Singleton @Component(modules = {AppModule.class}) 
public interface AppComponent { 

    void inject(MyClass clazz); 

    void inject(MyClass2 clazz); 

    ... 

    void inject(MyClassN clazz); 
} 

我寧願有來電component.inject()在每一個類,不是必須做的,隨着另一inject方法。


雖然相似,我不相信我的問題是重複的Dagger 2 Activity Injection Not Working。這個問題問爲什麼注射不起作用,答案是:因爲Dagger 2有很強的類型聯繫,你必須爲每個類別聲明一個inject方法。這個問題更側重於圍繞樣板,而希望保持強大的類型關聯。

+0

就我所瞭解的Dagger2而言,你的假設是正確的,即它只對每個要注入值的類都使用注入方法。據我所知,建議的解決方案是創建許多範圍內的組件,提供特定活動/片段或應用程序的一部分所需的內容。希望helpss –

+0

可能重複[匕首2活動注射不工作](http://stackoverflow.com/questions/29367921/dagger-2-activity-injection-not-working) –

+0

@MikaelOhlson這是令人沮喪的,考慮到我有目前大約有三十個片段,其中大部分依賴於「Retrofit」客戶端。更不用說任何類可能需要的所有其他依賴。 – Bryan

回答

1

我發現了一個漂亮的小技巧,用在AsymmetricFingerprintDialog示例應用程序中,但我不知道我是否完全理解它是如何工作的。該示例使用了Dagger的第一次迭代,但是快速測試表明它也適用於Dagger 2。

對於每個Fragment我添加一個空的構造與@Inject註釋,然後使用@Inject註釋在我Activity得到Fragment的一個實例。

public class MainActivity extends AppCompatActivity { 

    @Inject MyFragment mFragment; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     MyApplication.getComponent().inject(this); 
     getSupportFragmentManager().beginTransaction 
       .replace(R.id.fragment_container, mFragment).commit(); 
     ... 
    } 
} 

public class MyFragment extends Fragment { 

    @Inject MyDependency mDependency; 

    @Inject 
    public MyFragment() {} 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 
     mDependency.doSomething(); 
     ... 
    } 
} 

這讓我打電話給MyApplication.getComponent().inject(this)只在每個Activity,並依賴將被注入到Fragment類爲好。這樣,我只需要每個Activityinject方法,而不是每個Fragment

@Singleton @Component(modules = {AppModule.class}) 
public interface AppComponent { 

    void inject(MainActivity activity); 
} 

我很好奇它是如何工作的。從我所看到的與Dagger無關的事情來看,它似乎使用了@Inject註釋來達到預期目的?儘管我對匕首和JSR-330都是新手,但我不確定。


編輯:此方法僅適用setRetainInstanceState(true)工作,或者如果你保存和恢復自己的實例。

+1

要小心,因爲碎片可以由Android本身創建。所以在這種情況下,注射不會發生 –

+1

@EugenMartynov啊,我沒有想到這一點。你是對的,在方向改變時會出現'NullPointerException'。我認爲'Fragment'會在重新創建時被'Activity'重新創建,我想不是這樣的。 – Bryan