2016-09-12 3 views
7

現在、アクティビティでPicassoなどのインスタンスを取得するには、AppComponentにinjectメソッドを追加する必要があります。私はそれが注入されるべきフラグメントとビューの多くを持っているので、注入方法を追加しないようにする方法:各ビューの注入メソッドの追加を避けるにはどうすればよいですか?

をAppComponent.class:

@ForApplication 
@Singleton 
@Component(
     modules = {AppModule.class,OkHttpClientModule.class,NetworkApiModule.class,NetworkAuthModule.class}) 
public interface AppComponent { 
    void inject(Fragment1 obj); 
    void inject(Fragment2 obj); 
    void inject(Fragment3 obj); 
    void inject(Fragment4 obj);  
    void inject(Fragment5 obj);  
    void inject(Fragment6 obj); 
    ... 
    } 

Fragment1.class

public class Fragment1 extends Fragment { 
    @Inject Picasso mPicasso; 
    @Override 
    public void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     MyApplication.getComponent(getContext()).inject(this); 
    } 
} 

マイクラス:

AppModule.class:

@Module 
public class AppModule { 
    private MyApplication mApplication; 

    public AppModule(@NonNull MyApplication mApplication) { 
     this.mApplication = mApplication; 
    } 

    @Provides 
    @NonNull 
    @Singleton 
    public Application provideApplication() { 
     return mApplication; 
    } 


    @Provides 
    @ForApplication 
    Context provideContext(){ 
     return mApplication; 
    } 

    @Provides 
    @Singleton 
    Picasso providesPicasso(@ForApplication Context context) { 
     return new Picasso.Builder(context).build(); 
    } 
} 

ForApplication.class:

@Scope 
@Retention(RUNTIME) 
public @interface ForApplication { 
} 

MyApplication.class

public class MyApplicationextends Application { 
    static Context mContext; 
    private AppComponent component; 
    @Override 
    public void onCreate() { 
     super.onCreate(); 
     mContext = this; 

     setupComponent(); 
    } 

    private void setupComponent() { 
     component = DaggerAppComponent.builder().appModule(new AppModule(this)).build(); 
     component.inject(this); 
    } 

    public AppComponent getComponent() { 
     if (component==null) 
      setupComponent(); 
     return component; 
    } 



public static AppComponent getComponent(Context context) { 
     return ((MyApplication) context.getApplicationContext()).getComponent(); 
    } 

UPDATE

私も断片用のアダプタを注入し、私は追加しますならば、BaseFragmentに注入BaseFragmentたいですすべての子フラグメントのすべてのアダプタを持ちます

答えて

0

私はlombok library

@Accessors(prefix = "m") 
public class AdapterDelegate { 
    @Getter @Inject Lazy<FlatAdapter> mFlatAdapterLazy; 
    public AdapterDelegate(){ 
     MyApplication.getComponent(MyApplication.getContext()).inject(this); 
    } 

    public static AdapterDelegate get() { 
     return new AdapterDelegate(); 
    } 
} 

Delegate classを追加することによってそれを解決し、活動

public class MainActivity extends Activity { 
    FlatAdapter mFlatAdapter = AdapterDelegate.get().getFlatAdapterLazy().get(); 
2

1つの解決策は、注入に継承を使用することです。

@Inject PicassoインスタンスでBaseFragmentを定義し、このBaseFragmentのDaggerComponentに注入メソッドを作成し、BaseFragmentのonCreateメソッドで呼び出します。 Fragment1,2などのより具体的なフラグメントは、このBaseFragmentから継承し、Picassoインスタンスを使用できます。

+0

に私が破片のためのアダプタを注入したい、と私はBaseFragmentに注入を追加しますならば、BaseFragmentがありますすべての子フラグメントのすべてのアダプタ – NickUnuchek

+0

これらのアダプタは、ピカソプロバイダと同じコンポーネントからアクセスできますか?これらのアダプターはどのように異なっていますか? – Jacob

+0

私は@ジャコブがテーブルに良い答えを持っていると思うが、あなたが他のメンバーを注射しなければならないなら、あなたはそれらのために別々にこれをする選択肢がない! –

1

これはどうですか?

public final class MySimpleDelegate { 

    @Inject 
    protected Picasso picasso; 

    @Inject 
    protected Lazy<AdapterOne> lazyAdapterOne; 

    @Inject 
    protected Provider<AdapterTwo> providerAdapterTwo; 

    public MySimpleDelegate(Context context) { 
     MyApplication.getComponent(context).inject(this); 
    } 

    @NonNull 
    public void getPicasso() { 
     return picasso; 
    } 

    @NonNull 
    AdapterOne getAdapterOne() { 
     // the object is injected when the following method is called 
     return lazyAdapterOne.get(); 
    } 

    @NonNull 
    AdapterTwo getAdapterTwo() { 
     // a new instance is created every time this methos is called 
     return providerAdapterTwo.get(); 
    } 
} 

public class Fragment1 extends Fragment { 

    private MySimpleDelegate delegate; 

    @Override 
    public void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     delegate = new MySimpleDelegate(getContext()); 

     Picasso picasso = delegate.getPicasso(); 
     AdapterOne one = delegate.getAdapterOne(); 
     AdapterTwo two = delegate.getAdapterTwo(); 
    } 
} 

ところで、唯一の問題がPicassoである場合、「setSingletonInstance」メソッドも提供されます。私はあなたが短剣のプロバイダまたはレイジー工場を使用して欲しいものを達することができると信じていthis link

EDIT

を参照してください。上記の例を参照してください。

+0

このソリューションは、短剣の柔軟性を破ります。だから、TSが彼の断片に別の依存関係を追加したいのであれば、別の代理人を作成するか、結局その断片の挿入メソッドを作成するでしょう。 – Beloo

+0

私は本当にあなたのコメントを理解していません、どのような 'ダガー柔軟性'ですか? Daggerは一般的な注入ライブラリであり、フラグメントやアクティビティの内部で動作させる必要はありません(柔軟性があります)。このソリューションは、コンポーネントにすべての単一のビュー/フラグメント/アクティビティを追加することを避けるために、単にインジェクションを別のクラスに委譲しています(つまり、著者が要求したものです)。 –

+0

ターゲットフラグメントに20以上の依存関係があるとします。だから、あなたはそのようなアプローチでそれをどのように解決できますか? 20人以上の代表者を提供しますか?さらに、私たちのフラグメントがピカソ依存性しか持たない場合は、成長/スケーリングの準備ができていないので、これを合理的に使用することはできません。 – Beloo

1

ソリューションを使用すると、継承元を行うことができます:使用は、これらのクラス以下は

でのonCreate()を活動またはフラグメントを拡張し、で注入を行うには、私は何をすべきかの例です:

Graph.java

@Singleton 
@Component(modules = { 
     AppModule.class, 
}) 

public interface Graph { 

    void inject(BaseActivity activity); 
    void inject(BaseFragment fragment); 
} 

BaseActivity.java

public class BaseActivity extends AppCompatActivity { 
    protected List<Subscription> mSubscriptions; 

    @Inject 
    protected SharedDB dm; 

    @Inject 
    protected RestApi restApi; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getGraph().inject(this); 
    } 

    public Graph getGraph() { 
     return MyApplication.graph(this); 
    } 

    //... 
} 

BaseFragment.java

public class BaseFragment extends Fragment { 

    protected List<Subscription> mSubscriptions; 
    protected Unbinder unbinder; 

    @Inject 
    protected SharedDB dm; 

    @Inject 
    protected RestApi restApi; 

    @Override 
    public void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getGraph().inject(this); 
    } 

    public Graph getGraph() { 
     return MyApplication.graph(getActivity()); 
    } 

    //.... 
} 

MyApplication。Javaの

public class MyApplication extends Application { 

    private Graph mGraph; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     setGraph(DaggerGraph.builder() 
       .appModule(new AppModule(this)) 
       .build()); 
    } 

    public Graph getGraph() { 
     return mGraph; 
    } 

    public void setGraph(Graph graph) { 
     mGraph = graph; 
    } 

    public static Graph graph(Context context) { 
     DominoApp app = (DominoApp) context.getApplicationContext(); 
     return app.getGraph(); 
    } 

    //.... 
} 
-1

あなたは各対象クラスフラット方法を注入方法を追加することを避けることはできませんが、リフレクションを使用して、各クラスでその注入メソッドを呼び出す回避することができます。 this solutionを使用すると、注入メソッドを親クラスでのみ呼び出すことができ、ComponentReflectionInjectorは継承チェーンの各子クラスに依存関係を提供します。

のように、それがどのように見えるか:

Component { 
    void inject(Child b); 
} 

//Activity, fragment - no matter 
class Parent { 
    ComponentReflectionInjector componentReflectionInjector; 
    void onCreate() { 
     componentReflectionInjector = new ComponentReflectionInjector(Component.class, /* component instance*/); 
     componentReflectionInjector.inject(this); 
    } 
} 

//your fragment with Picasso 
class Child extends Parent { 
    @Inject MyDependency dependency; 
} 

そして、依存関係がChildクラスのonCreate方法でアクセス可能となってしまいます。非常にdisputable solutionある

は、それは価値便宜のためにいくつかのパフォーマンスを失うことでしょうし、それが難読化後のProGuardといくつかの可能性のある問題に値するだろう、とdagger2はDIフレームワークでは全くリフレクションを使用しないように設計されていますが、まだされています。

関連する問題