2016-02-23 139 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