15

F1 ve F2 sınıflarına ait nesnelerim korunan bir Parçacıkta enjekte etmek istiyorum. Ayrıca, Etkinliğe bağlı olarak A sınıfının bir nesnesine de sahibim ve bu Etkinlikte ve o Etkinliğin Fragman Yöneticisine eklenmiş bir Alıkonan Bölümde enjekte edilmesini istiyorum. Aşağıdaki kodu yazarım. İlk olarak, faaliyet bağımlılığı için modül: OHançer 2: Aktivitede aynı bağımlılığı enjekte edin ve Fragman

@Module 
public class MainActivityModule { 
    private Activity mActivity; 

    public MainActivityModule(Activity activity) { 
     mActivity = activity; 
    } 

    @Provides 
    @ActivityScope 
    public A provideA() { 
     return new A(mActivity); 
    } 
} 

, ilgili bileşenin, bu bağımlı bileşenlere uygun A nesne yapmak gerekir:

@ActivityScope 
@Component(modules = {MainActivityModule.class}) 
public interface MainActivityComponent { 
    void inject(MainActivity activity); 

    // make the A object available to dependent components 
    A getA(); 
} 

Ayrıca Fragman ile ilgili modül yazmak:

@Module 
public class FragmentModule { 
    @Provides 
    @FragmentScope 
    public F1 provideF1() { 
     return new F1(); 
    } 

    @Provides 
    @FragmentScope 
    public F2 provideF2() { 
     return new F2(); 
    } 
} 

ve karşılık gelen bileşen:

@FragmentScope 
@Component(modules = {FragmentModule.class}, dependencies = {MainActivityComponent.class}) 
public interface FragmentComponent { 
    void inject(MyFragment presenter); 
} 

Son olarak, özel yaşam döngüsü yöntemlerini de çağırmam gereken Etkinlikte A bağımlılığını enjekte ediyorum. Etkinlik ayrıca Fragment kendi bileşenini oluştururken kullanmak mümkün olacak şekilde bileşeni almak için bir yöntem sağlar:

// in MainActivity.onCreate 
mActivityComponent = DaggerMainActivityComponent.builder() 
     .mainActivityModule(new MainActivityModule(this)) 
     .build(); 
mActivityComponent.inject(this); 
mA.onCreate(); 

ve ben de Fragment, A üzerine F1, F2 bağımlılıkları enjekte etmek deneyin : Etkinlik tahrip olabilmekte ve bir yapılandırma değişikliği (örneğin, bir cihaz rotasyon) tepki sistemi tarafından yeniden edildiğinde Fragman, korunur Ancak

// in MyFragment.onCreate 
FragmentComponent component = DaggerFragmentComponent.builder() 
     .fragmentModule(new FragmentModule()) 
     .mainActivityComponent(((MainActivity) getActivity()).getComponent()) 
     .build(); 
component.inject(this); 

, Fragman ise, eski A örneği başvurusu tutar Yeni Etkinlik yeni biryeniden oluşturuldu Onunla gitmek içinörneği. Bu soruna geçici bir çözüm bulmak için , FragmentComponent oluşturmak ve MyFragment.onActivityCreated MyFragment.onCreate yerine enjekte bağımlıları gerekir. Diğer taraftan, bu, etkinlik her defasında ve yeniden oluşturulduğunda F1 ve F2 bağımlılıklarının yeniden yaratıldığını gösterir; Ancak bunlar, Fragment kapsamındaki bağımlılıklardır, bu yüzden Etkinliklerin yerine Fragment yaşam döngüsünü izlemelidirler. Bu nedenle benim sorum şu şekildedir: tutulan bir Fragmana enjekte edilen farklı kapsamlarda bağımlılıkların olması mümkün mü? İdeal olarak, F1 ve F2 bağımlılıkları MyFragment.onCreate'a enjekte edilmeli, A bağımlılığı ise MyFragment.onActivityCreated'a enjekte edilmelidir. İki farklı bileşen kullanmayı denedim, ancak kısmi enjeksiyon yapmak mümkün görünmüyor. Şu anda, MyFragment.onActivityCreated Fragmanı A bağımlılığı açık bir yeniden atama ekleyerek sona erdi, ama gerçekten enjeksiyon değil, biliyorsunuz. Bu daha iyi bir şekilde yapılabilir mi?

+1

Enjeksiyon dışında yaşam döngüleri vardır nesnelerle de çalmıyor senin kontrol (Etkinlikler gibi). Genellikle bir parça sadece ebeveyn aktivitesiyle çalışabilir, böylece enjeksiyondan gerçekten faydalanamazsınız. Ancak birim testleri için 'setA (A a)' yöntemini sağlayabilirsiniz, böylece değeri mock/test nesnesi ile geçersiz kılabilirsiniz. Ayrıca: Neden 2 ayrı bileşen kullanıyorsunuz ve grafikleri sırasıyla enjekte ediyorsunuz (bir uygulama geniş bileşeni yerine ve böylece uygulamanın başlamasında grafiğin yalnızca bir yapısına sahip oluyorsunuz)? – Ognyan

+0

@Ogre_BGR Zor olduğunu biliyorum, bu yüzden burada yardım istiyorum. Gördüğüm fayda, Faaliyete giren kod miktarının kırpılmasıyla ilgilidir; 'A' nesnesinde yaşam döngüsü ile ilgili çağrıları içermesi gerekir, ancak nesne gerçekten Fragment tarafından kullanıldığı için, bu kodun Etkinlik içinde değil, Fragmentte kalması gerekir. Yani kod organizasyonuyla ilgili bir şey değil, testler. Uygulama çapında bir bileşen kullanamıyorum çünkü “A” (üzerinde tam denetimim yok) bir Etkinlik örneğine (yalnızca bir Bağlam değil) sıkı bir bağımlılığa sahiptir. –

+0

u bir uygulama modülü yapabilir ve –

cevap

8

Alıkonan parçanızın etkinliğinizden daha uzun süre yaşandığını düşünürsek, bunu yapmanın doğru yolu, FragmentScope'un ActivityScope'u içermesi ve bunun tersi de geçerli değildir.

sizin FragmentComponent

@FragmentScope 
@Component(modules = {FragmentModule.class}) 
public interface FragmentComponent { 
    void inject(MyFragment presenter); 
} 

olurdu Ve Etkinlik bileşeni Fragment enjekte sınıfları bağımlılıkları olarak Etkinlik modülü güvenmeyin eğer mümkündür

@ActivityScope 
@Component(dependencies = {FragmentComponent.class}, modules = {MainActivityModule.class}) 
public interface MainActivityComponent extends FragmentComponent { //provision methods 
    void inject(MainActivity activity); 

    // make the A object available to dependent components 
    A getA(); 
} 

olurdu Anlamı.

Bu

public class MainActivity extends AppCompatActivity { 

    private MainActivityComponent mainActivityComponent; 

    private MyFragment myFragment; 

    @Override 
    public void onCreate(Bundle saveInstanceState) { 
     super.onCreate(saveInstanceState); 
     setContentView(R.layout.activity_main); 

     if(saveInstanceState == null) { // first run 
      myFragment = new MyFragment(); //headless retained fragment 
      getSupportFragmentManager() 
       .beginTransaction() 
       .add(myFragment, MyFragment.class.getName()) //TAG 
       .commit(); 
     } else { 
      myFragment = (MyFragment)(getSupportFragmentManager() 
           .findFragmentByTag(MyFragment.class.getName())); 
     } 
    } 

    @Override 
    public void onPostCreate() { 
     mainActivityComponent = DaggerMainActivityComponent.builder() 
       .fragmentComponent(myFragment.getComponent()) 
       .build(); 
    } 
} 

Ve

public class MyFragment extends Fragment { 
    public MyFragment() { 
     this.setRetainInstance(true); 
    } 

    private FragmentComponent fragmentComponent; 

    @Override 
    public void onCreate(Bundle saveInstanceState) { 
     super.onCreate(saveInstanceState); 
     this.fragmentComponent = DaggerFragmentComponent.create(); 
    } 

    public FragmentComponent getFragmentComponent() { 
     return fragmentComponent; 
    } 
} 

benzer bir şey ile yapılabilir DÜZENLEME:

public class MyFragment extends Fragment { 
    public MyFragment() { 
     this.setRetainInstance(true); 
     this.fragmentComponent = DaggerFragmentComponent.create(); 
    } 

    private FragmentComponent fragmentComponent; 

    public FragmentComponent getFragmentComponent() { 
     return fragmentComponent; 
    } 
} 

public class MainActivity extends AppCompatActivity { 

    private MainActivityComponent mainActivityComponent; 

    private MyFragment myFragment; 

    @Inject 
    A mA; 

    @Override 
    public void onCreate(Bundle saveInstanceState) { 
     super.onCreate(saveInstanceState); 
     setContentView(R.layout.activity_main); 

     if(saveInstanceState == null) { // first run 
      myFragment = new MyFragment(); //headless retained fragment 
      getSupportFragmentManager() 
       .beginTransaction() 
       .add(myFragment, MyFragment.class.getName()) //TAG 
       .commit(); 
     } else { 
      myFragment = (MyFragment)(getSupportFragmentManager().findFragmentByTag(MyFragment.class.getName())); 
     } 
     mainActivityComponent = DaggerMainActivityComponent.builder() 
       .fragmentComponent(myFragment.getComponent()) 
       .build(); 
     mainActivityComponent.inject(this); 
     mA.onCreate(); 
    } 
} 
+0

Bu çok ilginç bir şey, teşekkürler. Şu anda (uygulama henüz bitmedi) "Benim 'Parça' enjekte edilen sınıflar bağımlılık olarak Faaliyet modülüne güvenmiyor" aslında; ancak hala 'MainActivity.onCreate' içinde 'mA.onCreate' işlevini çağırmam gerekiyor ve bu çağrıyı 'MainActivity.onPostCreate' kadar geciktirebileceğime emin değilim. Akıllı çözümünle bile mümkün değil gibi görünüyor, değil mi? Oh, ve başka bir soru: Neden 'FragmentComponent '' MainActivityComponent' ile genişletmek gerekiyor? –

+0

Bu "mA.onCreate" ın çağırmanız gereken şeyi belirtmeniz gerekiyor, çünkü şu anda görmüyorum. 'onPostCreate()', 'forCreate()' yönteminin, Çalışmanın bileşenini oluşturmadan önce çalıştığından emin olmak için kullanılır ('her bir parçanın başlatılmasından sonra' onPostCreate() 'denir). Alt sınıfın olması durumunda, tedarik yöntemlerini elde etmek için bileşeni genişletirim. – EpicPandaForce

+0

"Şu anda görmüyorum" ile ne demek istiyorsun? Sorunun son bir kod snippet'inde var. Ben sadece bir yorum yazdım ('MainActivity' anlamına geliyordu 'MyActivity' yazdım) ama çağrı her zaman orada olmuştur. –