1

私は Android アプリケーションの MVC パターンに従っていますが、この問題に数回遭遇し、回避する必要がありました。 私のアプリケーションがフィールドで @Inject アノテーションを使用して注入されたオブジェクトを作成できる場合、そのオブジェクトの @Inject フィールドは null であり、通常はクラッシュを引き起こします。 たとえば、ロジックとフローを処理するコントローラー クラスがあります。フラグメント/アクティビティはコントローラーにコールバックして、ユーザーの操作/状態の変化を通知します。ただし、挿入された Controller のインスタンスは通常 null です。

簡単な例を挙げて説明します。以下では、コントローラーに挿入されたアクティビティが作成され、それを使用してフラグメントを追加してフローを開始しています。その依存関係は処理されますが、コントローラーのアクティビティの依存関係は処理されません (つまり、null)。

ビジネス ロジックとフローを処理する単純なコントローラー クラス:

public class SomeController {
    @Inject
    SomeActivity someActivity;

    private SomeComponent component;

    private final Application app;

    @Inject
    public SomeController(Application app) {
        this.app = app;
    }

    private void startActivity() {
        component = Dagger_SomeComponent().builder()
             .someModule(app)
             .build();

        someActivity.getFragmentManager().beginTransaction().
            .add(R.id.content, SomeFragment.class, null)
            .commit();
    }

    public void activityStarted() {
        //callback when Activity is ready...
    }
}

ユーザーの操作を処理し、コントローラーにコールバックしてビジネス ロジックを実行する単純なアクティビティ:

public class SomeActivity extends Activity {

    @Inject
    SomeController controller;

    private void controllerCallback() {
          //notify controller of something here...
    }
}

オブジェクトをグラフに挿入するための単純なモジュール クラス:

@Module
public class SomeModule {

    private Application app;

    public SomeModule(Application app) {
         this.app = app;
    }

    @Provides
    @Singleton
    SomeController provideSomeController( return new SomeController(app); )

    @Provides
    SomeActivity provideSomeActivity( return new SomeActivity();)
}

オブジェクトを消費するメソッドを提供する単純な Component クラス:

@Component
public interface SomeComponent {

    void addController(SomeController controller);

    SomeController controller();

    SomeActivity activity();
}
4

3 に答える 3

1

この問題に遭遇し、この受け入れられた回答を使用して解決しました。

TLDR:inject()コンポーネントに正確な型のメソッドを追加する必要がありました。inject(SomeSuperclass foo)

基本的に、注入が必要なアクティビティがありました:

class SubActivity extends BaseActivity {
    @Inject Type someVar;

    @Override
    protected void onCreate(Bundle bundle) {
       getComponent().inject(this);
    }
}

しかし、私のコンポーネントは次のように見えました:

@Component
public interface MyComponent {
    void inject(BaseActivity activity); // This allows SubActivity to compile but messes up injection
}

解決策:正確なサブタイプの注入メソッドを追加します。

@Component
public interface MyComponent {
    void inject(BaseActivity activity);
    void inject(SubActivity activity); //<-- This solved it
}
于 2015-05-15T07:48:26.207 に答える
1

あなたの例ではいくつかのことが見逃されていると思います:

1) Dagger2 コンポーネントは、依存関係を提供するいくつかのモジュールと、依存関係を「消費」するいくつかの注入ポイントとの間のブリッジです。コンポーネントには少なくとも 1 つのリンクされたモジュールが必要であり、注釈は次のようになります。

@Component(modules = SomeModule.class)

2) 「new」演算子を使用したモジュールでの SomeActivity インスタンス化は意味がありません。さて、Activity オブジェクトを作成することはできますが、その状態を管理したり、ライフサイクル メソッドを呼び出したりするのは誰でしょうか? 既存の Activity の参照を依存関係として本当に渡したい場合は可能ですが、方法が異なります。たとえば、アプリケーション レベルのモジュールとコンポーネント、および別のアクティビティ レベルのモジュールとコンポーネントを作成し、既存のアクティビティ参照をモジュール コンストラクター引数として渡します。

3) アクティビティは Android フレームワークによって作成されるため、アクティビティではフィールド インジェクションを使用する必要があります。次のような行をコンポーネントに追加します。

void inject(SomeActivity activity);

Component を作成するコードを Activity に配置します。たとえば onCreate() の場合:

SomeComponent component = Dagger_SomeComponent().builder()
         .someModule(getApplication())
         .build()
         .inject(this);

4) 先頭に @Singleton アノテーションを付けないようにしてください。最初に、宣言されているすべての依存関係が満たされ、null がないことを確認します。次に、いくつかの既存の Dagger2 オープン ソース プロジェクトをチェックして、適切なスコープ アノテーションを作成できます。

于 2015-03-20T21:41:23.230 に答える
0

私の場合、depends-on="bean1" は application-context の property-placeholder 内にあり、問題を引き起こしていました。@PostConstruct を使用してインジェクションを機能させました。

于 2020-02-25T15:23:16.030 に答える