1

私は自分の Android アプリを「短剣化」していますが、それが自分のせいなのかフレームワークのせいなのかわからない小さな問題に直面しています。それが私なら、私は自分自身に非常に失望するでしょう:)

提供する次のクラスがあります。

@Singleton
public class XmlService {

    private final DataCommitter<XmlWritable> mXmlCommitter;
    private final DataReader<XmlPushable> mXmlReader;
    private final ConcurrentObjectMonitor mConcObjMonitor;

   @Inject
   public XmlService(DataCommitter<XmlWritable> xmlCommitter,
        DataReader<XmlPushable> xmlProvider,
        ConcurrentObjectMonitor concObjMonitor) {
    mXmlCommitter = xmlCommitter;
    mXmlReader = xmlProvider;
    mConcObjMonitor = concObjMonitor;
   }

次の(とりわけ)クラスを使用:

public class XmlDataReader implements DataReader<XmlPushable> {
  // No Singleton no more.
  // Eager Singleton (Therefore it should be made thread safe)
  //static XmlDataReader mInstance = new XmlDataReader();
  [CUT]

  protected XmlPullParser mXmlPullParser;

  @Inject
  public void XmlDataRead(XmlPullParser xmlPullParser) {
      mXmlPullParser = xmlPullParser;
  }

このクラスは、私の XmlServiceModule で次のように参照されます。

@Module(complete = true)
public class XmlServiceModule {

    @Provides DataReader<XmlPushable> provideDataReader(XmlDataReader dataReader) {
        return dataReader;
    }
}

さて、問題は、提供されたクラスを注入することは合法ですか? XmlDataReader ctor の @Inject でエラーが発生しているため、public void XmlDataRead(org.xmlpull.v1.XmlPullParser) を注入できません。


編集: 申し訳ありませんが、私のサンプル コードにエラーがありましたが、以下のクリスチャンの回答を理解するために役立つ可能性があるため、そのままにしておきます。

4

1 に答える 1

3

実際、サンプルコードにエラーがあります。注入可能なコンストラクターはありません。インスタンスメソッドを注入することはできず、コンストラクターのみを注入することができ、そのメソッドが呼び出されることはありません。

あなたが持っている必要があります:

public class XmlDataReader implements DataReader<XmlPushable> {

  protected final XmlPullParser mXmlPullParser;

  @Inject
  public XmlDataReader(XmlPullParser xmlPullParser) {
      mXmlPullParser = xmlPullParser;
  }
}

このように、それはコンストラクターであり、適切に注入されます。

全体的なアプローチに関しては、あなたは正しい方向にいます。あなたは、あなたのprovidesメソッドで@Provide DataReader<XmlPushable効果的にそれにバインドします。XmlDataReaderここまでは順調ですね。ダガーは、要求されたときにDataReader<XmlPushable>そのバインディングを使用し、依存関係を効果的にパススルーし、XmlDataReaderこれを満たすために提供します。

XmlDataReaderには@Inject注釈付きのコンストラクターがあるため、Daggerの分析では「注入可能なタイプ」と見なされるため、を提供する必要はありません@Provides。注釈付きコンストラクターXmlPullParserがあるか、モジュールのメソッドで提供されているものがある限り、ここでコーディングしたものは良いように見えますが、完全ではありません。@Inject@Provides

@ModuleにentryPointがリストされていないため、ObjectGraphから最初に取得するクラスが必要です。したがって、このコードは、それが進む限り合理的ですが、不完全です。(フィールドまたはコンストラクターを介して)注入するものが必要ですDataReader<XmlPushable> 。たとえば、これを行うaFooActivityを作成できます。

検討:

public class XmlDataReader implements DataReader<XmlPushable> {    
  protected XmlPullParser mXmlPullParser;

  @Inject public XmlDataReader(XmlPullParser xmlPullParser) {
    mXmlPullParser = xmlPullParser;
  }
}

@Module(entryPoints = { FooActivity.class, BarActivity.class })
public class XmlServiceModule {
  @Provides DataReader<XmlPushable> provideDataReader(XmlDataReader dataReader) {
    return dataReader;
  }

  @Singleton
  @Provides XmlPullParserFactory parserFactory() {
     XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
     factory.setNamespaceAware(true);
     return factory;
  }

  @Provides XmlPullParser parser(XmlPullParserFactory factory) {
     XmlPullParser xpp = factory.newPullParser();
  }
}

public class YourApp extends Application {
  private ObjectGraph graph;

  @Override public void onCreate() {
    super.onCreate();
    graph = ObjectGraph.get(new ExampleModule(this));
  }

  public ObjectGraph graph() {
    return objectGraph;
  }
}

public abstract class BaseActivity extends Activity {
  @Override protected void onCreate(Bundle state) {
    super.onCreate(state);
    ((YourApp) getApplication()).objectGraph().inject(this);
  }
}

class FooActivity extends BaseActivity {
  @Inject DataReader<XmlPushable> reader;

  @Override public void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    // custom Foo setup
  }
}

class BarActivity extends BaseActivity {
  @Inject DataReader<XmlPushable> reader;

  @Override public void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    // custom Bar setup
  }
}

これはおそらくあなたが望むものに近いです。すべてのものはエントリポイントから到達可能であり、依存するすべてのものはバインドされています。2つのアクティビティは、「エントリポイント」(オブジェクトグラフのルート)です。それらが初期化されると、最終的には自分自身でObjectGraph'sinject(Object)メソッドを呼び出します。これにより、Daggerは@Inject注釈付きフィールドを挿入します。これらのフィールドは、DataReader<XmlPushable>XmlPullParserを使用して提供されるXmlPullParserで提供されるXmlDataReaderによって満たされるフィールドです。それはすべて依存関係の連鎖を流れます。

小さなメモ-@Module(complete=true)がデフォルトです。不完全である場合を除き、完全を指定する必要はありません。false

于 2013-02-13T05:23:02.940 に答える