2016-09-12 13 views
7

Şu anda bir etkinlikte örneğin Picasso örneğini elde etmek için, AppComponent'e enjekte etme yöntemini eklemem gerekiyor.Her görünüm için enjeksiyon yönteminin eklenmesi nasıl engellenir?

AppComponent.class: Ben enjekte edilmelidir parçaları ve çok sayıda görüntüleme var çünkü, enjekte yönteminin eklemekten kaçının Nasıl

@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); 
    } 
} 

Benim sınıfları:

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(); 
    } 

GÜNCELLEME

Ben de parçaları için adaptörleri enjekte ve ben ekleyeceğiz o zaman BaseFragment için enjekte BaseFragment istiyorum tüm çocuk parçaları

cevap

0

Ben 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(); 
    } 
} 

ile Delegate class ekleyerek Ve

public class MainActivity extends Activity { 
    FlatAdapter mFlatAdapter = AdapterDelegate.get().getFlatAdapterLazy().get(); 
2
için tüm bağdaştırıcılara sahip olacak Enjeksiyon için bir çözüm, kalıtımın kullanılması olacaktır.

Yalnızca bir Picasso örneği içeren bir BaseFragment tanımlayın, bu BaseFragment için DaggerComponent öğesinde bir enjeksiyon yöntemi oluşturun ve BaseFragment öğesinin onCreate yönteminde çağırın. Fragment1, 2 .. gibi daha spesifik Fragmanlar bu BaseFragment'ten miras alabilir ve Picasso örneğini kullanabilir.

+0

Ben parçaları için adaptörler enjekte etmek istediğiniz bir Aktivite bunu çözdü ve BaseFragment için enjekte ekleriz o zaman BaseFragment olacak Tüm çocuk parçaları için tüm adaptörler – NickUnuchek

+0

Bu Adaptörler, picasso sağlayıcınızla aynı bileşende erişilebilir mi? Bu adaptörler birbirinden nasıl farklıdır? – Jacob

+0

Sanırım @Jacob masaya iyi bir cevap getiriyor, ama eğer başka üyeler enjekte etmeniz gerekiyorsa, hepsini ayrı ayrı yapmak için seçeneğiniz yok! –

1

Buna ne dersiniz? Tek sorun Picasso ise arada

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(); 
    } 
} 

, aynı zamanda bir 'setSingletonInstance' yöntem sağlar. Ben size hançerin Sağlayıcı ya Tembel fabrikaları kullanarak istediğiniz ne ulaşabilir inanıyoruz DÜZENLEME

this link

bakınız. Yukarıdaki örneğe bakınız.

+0

Bu çözüm hançer esnekliğini bozar. Dolayısıyla eğer TS, parçasına başka bir bağımlılık eklemek istiyorsa, başka bir delege oluşturacaktı ya da o parça için enjekte etme yöntemi yaratacaktır. – Beloo

+0

Gerçekten senin yorumunu anlamıyorum, 'hançer esnekliği' nedir? Hançer genel bir enjeksiyon kütüphanesidir ve parçanın veya faaliyetlerin içinde çalışmasına izin verilmesine gerek yoktur (esnekliği). Bu çözüm, bileşene her bir görünümü/parçayı/aktiviteyi eklemekten kaçınmak için enjeksiyonu başka bir sınıfa delege etmektir (yazarın istediği şey budur). –

+0

Varsayalım, bu hedef parçanın 20'den fazla bağımlılığı var. Peki bunu böyle bir yaklaşımla nasıl çözebilirsiniz? 20'den fazla delege verir misiniz? Dahası, eğer parçamız sadece pikona bağımlı olsaydı bunu kullanmak mantıklı değil, çünkü büyümeye/ölçeklemeye hazır olmayacaktır. – Beloo

1

çözümü miras ex yapabilirsiniz geçerli: kullanmam sınıfa Aşağıda

yılında onCreate() Aktivite veya Fragment genişletmek ve yılında enjeksiyon yapmak i ne örnektir:

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

Her hedef sınıfı düz yol için iğne yöntemi ekleme kaçınamaz ama yansımaları kullanarak her sınıfta o enjekte yöntemini çağırarak önleyebilirsiniz. this solution ile, yalnızca üst sınıftaki enjekte yöntemini çağırabilirsiniz ve daha sonra ComponentReflectionInjector, kalıtım zincirindeki her alt sınıf için bağımlılıklar sağlayacaktır.

gibi görüneceğini nasıl

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; 
} 

Sonra bağımlılıkları Child sınıfının onCreate yönteminde erişilebilir olmuştur olacaktır. çok disputable solution olduğunu

değer kolaylık bazı performans kaybetmesine olur ve onu gizleme sonra ProGuard ile olası bazı problemler değerinde olur ve dagger2 DI çerçeveler içinde hiç yansıma kullanmayın için tasarlanmış, ama yine edilmiştir.

İlgili konular