2017-02-28 7 views
1

こんにちは私は他の記事を読んだことがありますが、修正できません。基本的に私の問題は私が.injectを呼び出すことであり、フィールドを使用したいときはまだnullです。ダガー2ヌルフィールド注入

私はこのクラスを持っている:

public class Application extends Game implements IApplication { 

    @Inject IApplication app; 
    @Inject IRouter router; 

    public Application(IPlatformCode platformCode) { 

    } 

    @Override 
    public void create() { 
     initDagger(); 
     System.out.println(app); //NULL 
     System.out.println(router); //NULL 
     router.showPage(Page.MenuPage); //NULL EXCEPTION 
    } 

    @Override 
    public void render() { 
     Gdx.gl.glClearColor(1, 0.5f, 1, 1); 
     Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
     super.render(); 
    } 

    @Override 
    public void setPage(IPage page) { 
     setScreen(page); 
    } 

    protected void initDagger() { 
     ApplicationComponent.Initializer.init(this).inject(this); 
     RouterComponent.Initializer.init().inject(this); 
    } 
} 

私はアプリで同じことをやっているので、私はルータが表示されません。

私のアプリケーション・コンポーネントは、次のようになります。

@Singleton 
@Component (modules = {ApplicationModule.class }) 
public interface ApplicationComponent { 
    void inject(IApplication application); 
    IApplication getApplication(); 
    static final class Initializer { 
     private Initializer(){} 
     public static ApplicationComponent init(IApplication app) { 
      return DaggerApplicationComponent 
        .builder() 
        .applicationModule(new ApplicationModule(app)) 
        .build(); 
     } 
    } 
} 

そして、これはモジュールです:

@Module 
public class ApplicationModule { 
    private IApplication app; 

    public ApplicationModule(IApplication app) { 
     this.app = app; 
    } 

    @Provides 
    @Singleton 
    public IApplication providesApplication(){ 
     return app; 
    } 
} 

私の知る限り(IApplication)を注入呼び出した後に読んで@Inject IApplicationを注入する必要があると値を持っていますが、今はnullです。事前に

public final class DaggerApplicationComponent implements ApplicationComponent { 
    private Provider<IApplication> providesApplicationProvider; 

    private DaggerApplicationComponent(DaggerApplicationComponent.Builder builder) { 
     assert builder != null; 

     this.initialize(builder); 
    } 

    public static DaggerApplicationComponent.Builder builder() { 
     return new DaggerApplicationComponent.Builder(); 
    } 

    private void initialize(DaggerApplicationComponent.Builder builder) { 
     this.providesApplicationProvider = DoubleCheck.provider(ApplicationModule_ProvidesApplicationFactory.create(builder.applicationModule)); 
    } 

    public void inject(IApplication application) { 
     MembersInjectors.noOp().injectMembers(application); 
    } 

    public IApplication getApplication() { 
     return (IApplication)this.providesApplicationProvider.get(); 
    } 

    public static final class Builder { 
     private ApplicationModule applicationModule; 

     private Builder() { 
     } 

     public ApplicationComponent build() { 
      if(this.applicationModule == null) { 
       throw new IllegalStateException(ApplicationModule.class.getCanonicalName() + " must be set"); 
      } else { 
       return new DaggerApplicationComponent(this); 
      } 
     } 

     public DaggerApplicationComponent.Builder applicationModule(ApplicationModule applicationModule) { 
      this.applicationModule = (ApplicationModule)Preconditions.checkNotNull(applicationModule); 
      return this; 
     } 
    } 
} 

ありがとう:

生成されたコードは次のようになります。

+0

プロジェクトを構築して、ダガーコードで生成されたものを確認してください。 'app'は本当に注入されていますか? 'DaggerApplicationComponent'と' DaggerRouterComponent'は正しく生成されていますか? 'ApplicationComponent'は本当に' ApplicationModule'から 'app'を提供していますか? – EgorD

+0

私はDaggerApplicationComponentが正しく構築されるようにプロジェクトをビルドしました。私はそれが助けになる場合には、生成されたコードを投稿に追加します。 – mrk

+0

'RouterComponent'は' ApplicationComponent'のサブコンポーネントですか? 1つの '@Singleton'コンポーネントしか持たないと思います。 私には分かりませんが、 'ApplicationComponent'のinitメソッドに渡しているのは、' Application'だけで、同じインスタンスを自分自身に注入するようです。これは、すべてが配線されていることをテストするためだけですか? – benji

答えて

1

あなたの注入方法は、

void inject(Application application); 

ノートにIApplicationにだけ適用からの変更を変更する必要があります。インジェクションメソッドにインターフェイスを使用することはできません。クラスを使用する必要があります。

+0

ええ、これは問題だと分かりました。私は前の記事でそれをコメントしました。ありがとう! – mrk

0

通常、Dagger 2コンポーネントの作成は、Androidのアプリケーションクラスの1つを拡張したクラスで行われます。これは主に、これらのコンポーネント(およびそれらが保持する依存関係)が一度だけインスタンス化されるようにするために行われます。 (詳細はDaggerのドキュメントを参照してください:https://google.github.io/dagger/users-guide

私はあなたがそれを別の方法で配線することはできないと言われていませんが、私はその例も見つけていません。あなたが作っているInitializer.init()呼び出しを使ってオンザフライでコンポーネントをワイヤリングしようとするとDaggerがインジェクションのためにコンポーネントを正しく設定することをバイパスしているかどうか疑問に思っています。代わりにコンポーネントクラスのインスタンス化をアプリケーション実装にリファクタリングすることは可能でしょうか?

上記のコードは動作するはずです(Singletonの代わりにすべてのinit()呼び出しで新しいDaggerApplicationComponentインスタンスを取得する以外)、私は本当になぜそうでないのか説明できません。

void inject(IApplication application); 

+0

問題は、モジュールの残りのすべてで、そこにルータを初期化したいのですが、別のページに移動するためにそこにそれを使用する必要があります。だからこそ私はこれを好きにしたのです。他の場所では、コンストラクタインジェクションを使うとうまくいくでしょう。最後の点として、initDaggerはエントリポイントであるcreate()から一度だけ呼び出され、もう一度呼び出されるべきではありません。なぜ私は様々なDaggerApplicationComponentsをインスタンス化するのか分からない。 – mrk

+1

サイドノート、これはLibGDXであり、Android .onCreateはアプリケーション.createを呼び出します。 – mrk

+0

問題は私がインターフェイスを使用していたことです。たとえば、IRouterはモジュールから新しいRouter()を返すべきですが、そうではありません。明らかにダガーはその権利を割り当てていません。私はインターフェイスの代わりにクラスに切り替えると、それは働いた。インスタンスを使用する方法はありますか?私はそれを行うのが好きです。私は行の実装を変更するだけです。私はモジュールのインスタンス化を変更することができますが、それ以外の場所ではIRouterを期待しています。 – mrk

関連する問題