Birden fazla Gradle modülü bulunan projeler çok modüllü proje olarak bilinir.
Özelliği olmayan tek bir APK olarak sunulan çok modüllü bir projede
çoğuna bağımlı olabilen bir app modülüne sahip olmak,
ve bir base ya da core modülüne sahip olursunuz.
bağlı olarak değişiklik gösterir. app modülü genellikle
Application sınıfı, base
modülü, projenizdeki tüm modüllerde paylaşılan tüm ortak dersleri içerir.
app modülü, uygulama bileşeninizi beyan etmek için iyi bir yerdir (
örnek, aşağıdaki resimde ApplicationComponent), nesnelerin
uygulamanızın tekil bileşenlerinin yanı sıra başka bileşenleri de test edebilirsiniz. Kullanıcı
OkHttpClient gibi sınıflar, JSON ayrıştırıcılar, veritabanınıza erişimciler,
core modülünde tanımlanabilecek SharedPreferences nesne,
app modülünde tanımlanan ApplicationComponent tarafından sağlanır.
app modülünde, daha kısa ömürlü başka bileşenler de bulunabilir.
Kullanıcıya özel yapılandırmaya sahip bir UserComponent örnek olarak gösterilebilir
(UserSession gibi).
Projenizin farklı modüllerinde en az bir tane tanımlayabilirsiniz. Şekil 1'de görüldüğü gibi, o modüle özgü bir mantığa sahip alt bileşendir.
Şekil 1. Dagger grafiği örneği çok modüllü proje
Örneğin, bir login modülünde LoginComponent
Yaygın nesneleri sağlayabilecek özel bir @ModuleScope ek açıklamasıyla kapsamlıdır
LoginRepository örneğinde bulabilirsiniz. Bu modülde şunları da yapabilirsiniz:
özel bir LoginComponent öğesine bağlı başka bileşenlere sahip
kapsam, örneğin @FeatureScope için LoginActivityComponent veya
Özelliğe daha özgü mantığın kapsamına girebileceğiniz TermsAndConditionsComponent
ViewModel nesne gibi.
Registration gibi diğer modüllerde benzer kuruluma sahip olursunuz.
Çok modüllü projeler için genel kural olarak, aynı seviyedeki modüllerin birbirine bağımlı olmamalıdır. Varsa ortak bir mantığa (aradaki bağımlılıklar) üst modülün bir parçası olmalıdır. Öyleyse, sınıfları üst modüle taşımak için yeniden düzenleme; Modül yoksa yeni bir modül oluşturun hem de orijinal modüllerin her ikisine de sahip kullanabilirsiniz.
En iyi uygulama olarak, bir bileşeni genellikle modülünü kullanabilirsiniz:
LoginActivityComponentişleminde olduğu gibi alan yerleştirme işlemi gerçekleştirmeniz gerekir.LoginComponent'de olduğu gibi nesnelerin kapsamını belirlemeniz gerekir.
Bu durumların ikisi de geçerli değilse ve Dagger'a bu durumu
nesnelerini oluşturmak için bir Dagger modülü oluşturun ve @Provides ya da
Bu sınıflar için inşaat yerleştirme mümkün değilse @Binds yöntemleri.
Dagger alt bileşenleriyle uygulama
Android uygulamalarında Dagger'ı kullanma doküman sayfasında, uygulama oluşturma ve kullanma
alt bileşenlerde bulunur. Ancak, aynı kodu kullanamazsınız çünkü
özellik modüllerinin app modülü hakkında bilgi sahibi olmadığını unutmayın. Örneğin, projenizin
giriş akışı ve önceki sayfada bulunan kod hakkında
derleyin:
Kotlin
class LoginActivity: Activity() { ... override fun onCreate(savedInstanceState: Bundle?) { // Creation of the login graph using the application graph loginComponent = (applicationContext as MyDaggerApplication) .appComponent.loginComponent().create() // Make Dagger instantiate @Inject fields in LoginActivity loginComponent.inject(this) ... } }
Java
public class LoginActivity extends Activity { ... @Override protected void onCreate(Bundle savedInstanceState) { // Creation of the login graph using the application graph loginComponent = ((MyApplication) getApplicationContext()) .appComponent.loginComponent().create(); // Make Dagger instantiate @Inject fields in LoginActivity loginComponent.inject(this); ... } }
Bunun nedeni, login modülünün MyApplication veya
appComponent. Bunu yapmak için özellikte bir arayüz tanımlamanız gerekir.
MyApplication ürününün ihtiyaç duyduğu bir FeatureComponent sağlayan modül
pek çok yolu vardır.
Aşağıdaki örnekte, bir LoginComponentProvider arayüzü tanımlayabilirsiniz
login modülünde Giriş akışı için bir LoginComponent sağlar:
Kotlin
interface LoginComponentProvider { fun provideLoginComponent(): LoginComponent }
Java
public interface LoginComponentProvider { public LoginComponent provideLoginComponent(); }
Artık LoginActivity, kod snippet'i yerine bu arayüzü kullanacak.
aşağıda tanımlandığı gibi:
Kotlin
class LoginActivity: Activity() { ... override fun onCreate(savedInstanceState: Bundle?) { loginComponent = (applicationContext as LoginComponentProvider) .provideLoginComponent() loginComponent.inject(this) ... } }
Java
public class LoginActivity extends Activity { ... @Override protected void onCreate(Bundle savedInstanceState) { loginComponent = ((LoginComponentProvider) getApplicationContext()) .provideLoginComponent(); loginComponent.inject(this); ... } }
Şimdi, MyApplication uygulamasının bu arayüzü uygulaması ve
gerekli yöntemler:
Kotlin
class MyApplication: Application(), LoginComponentProvider { // Reference to the application graph that is used across the whole app val appComponent = DaggerApplicationComponent.create() override fun provideLoginComponent(): LoginComponent { return appComponent.loginComponent().create() } }
Java
public class MyApplication extends Application implements LoginComponentProvider { // Reference to the application graph that is used across the whole app ApplicationComponent appComponent = DaggerApplicationComponent.create(); @Override public LoginComponent provideLoginComponent() { return appComponent.loginComponent.create(); } }
Çok modüllü bir projede Dagger alt bileşenlerini bu şekilde kullanabilirsiniz. Özellik modüllerinde çözüm, Google'ın birbirine bağlıdır.
Özellik modülleriyle bileşen bağımlılıkları
Özellik modüllerinde modüllerin çalışma şekli genellikle
içeren ters çevrilmiştir. Özellik içeren app modülü yerine
modüllerinde, özellik modülleri app modülüne bağlıdır. Şekil 2'ye bakın
temsil eder.
Şekil 2. Dagger grafiği örneği özellik modülleri içeren proje
Dagger'da, bileşenlerin alt bileşenleri hakkında bilgi sahibi olması gerekir. Bu bilgiler
üst bileşene (örneğin,
SubcomponentsModule modülüne ait bilgileri Android uygulamalarında Dagger kullanma başlıklı makalede bulabilirsiniz.
Ne yazık ki uygulama ile
özellik modülünde değilse alt bileşen, app modülünden
derleme yolunda değildir. Örneğin, LoginComponent
login özellik modülü
ApplicationComponent, app modülünde tanımlandı.
Dagger, müşterilerin ihtiyaçlarını karşılamak için bileşen bağımlılıkları adlı bir mekanizmaya sahiptir. çözer. Alt bileşen, üst bileşene, alt bileşen de üst bileşene bağımlıdır. Entegre alt-üst ilişkisinin olmadığını; bileşenler artık diğer kullanıcılara belirli bağımlılıkları elde etmeniz gerekir. Bileşenlerin grafikteki türleri göstermesi gerekir bağımlı bileşenlerin tüketilmesine de izin veriliyor.
Örneğin: login adlı bir özellik modülü
Şu bağlamda kullanılabilen AppComponent değerine bağlı olarak LoginComponent:
app Gradle modülü.
Aşağıda, şu sınıfın bir parçası olan sınıfların ve AppComponent için tanımlar:
app Gradle modülü:
Kotlin
// UserRepository's dependencies class UserLocalDataSource @Inject constructor() { ... } class UserRemoteDataSource @Inject constructor() { ... } // UserRepository is scoped to AppComponent @Singleton class UserRepository @Inject constructor( private val localDataSource: UserLocalDataSource, private val remoteDataSource: UserRemoteDataSource ) { ... } @Singleton @Component interface AppComponent { ... }
Java
// UserRepository's dependencies public class UserLocalDataSource { @Inject public UserLocalDataSource() {} } public class UserRemoteDataSource { @Inject public UserRemoteDataSource() { } } // UserRepository is scoped to AppComponent @Singleton public class UserRepository { private final UserLocalDataSource userLocalDataSource; private final UserRemoteDataSource userRemoteDataSource; @Inject public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) { this.userLocalDataSource = userLocalDataSource; this.userRemoteDataSource = userRemoteDataSource; } } @Singleton @Component public interface ApplicationComponent { ... }
app gradle modülünü içeren login gradle modülünüzde
LoginViewModel örneği yerleştirilmesi gereken LoginActivity:
Kotlin
// LoginViewModel depends on UserRepository that is scoped to AppComponent class LoginViewModel @Inject constructor( private val userRepository: UserRepository ) { ... }
Java
// LoginViewModel depends on UserRepository that is scoped to AppComponent public class LoginViewModel { private final UserRepository userRepository; @Inject public LoginViewModel(UserRepository userRepository) { this.userRepository = userRepository; } }
LoginViewModel, kullanılabilir UserRepository verisine dayalı bir bağımlılığa sahip ve
AppComponent olarak ayarlanır. Şuna bağlı bir LoginComponent oluşturalım:
LoginActivity eklemek için AppComponent:
Kotlin
// Use the dependencies attribute in the Component annotation to specify the // dependencies of this Component @Component(dependencies = [AppComponent::class]) interface LoginComponent { fun inject(activity: LoginActivity) }
Java
// Use the dependencies attribute in the Component annotation to specify the // dependencies of this Component @Component(dependencies = AppComponent.class) public interface LoginComponent { void inject(LoginActivity loginActivity); }
LoginComponent, AppComponent kaynağına ekleyerek bir bağımlılığı belirtir.
bağımlılık ek açıklamasına karşılık gelir. Çünkü LoginActivity,
bir mekanizmanın Dagger tarafından yerleştirilmesi için arayüze inject() yöntemini ekleyin.
Bir LoginComponent oluşturulurken AppComponent örneğinin şöyle olması gerekir:
başarılı oldu. Bu işlemi yapmak için bileşeni fabrika ayarlarına kullanın:
Kotlin
@Component(dependencies = [AppComponent::class]) interface LoginComponent { @Component.Factory interface Factory { // Takes an instance of AppComponent when creating // an instance of LoginComponent fun create(appComponent: AppComponent): LoginComponent } fun inject(activity: LoginActivity) }
Java
@Component(dependencies = AppComponent.class) public interface LoginComponent { @Component.Factory interface Factory { // Takes an instance of AppComponent when creating // an instance of LoginComponent LoginComponent create(AppComponent appComponent); } void inject(LoginActivity loginActivity); }
Artık LoginActivity, LoginComponent öğesinin bir örneğini oluşturabilir ve
inject() yöntemi.
Kotlin
class LoginActivity: Activity() { // You want Dagger to provide an instance of LoginViewModel from the Login graph @Inject lateinit var loginViewModel: LoginViewModel override fun onCreate(savedInstanceState: Bundle?) { // Gets appComponent from MyApplication available in the base Gradle module val appComponent = (applicationContext as MyApplication).appComponent // Creates a new instance of LoginComponent // Injects the component to populate the @Inject fields DaggerLoginComponent.factory().create(appComponent).inject(this) super.onCreate(savedInstanceState) // Now you can access loginViewModel } }
Java
public class LoginActivity extends Activity { // You want Dagger to provide an instance of LoginViewModel from the Login graph @Inject LoginViewModel loginViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Gets appComponent from MyApplication available in the base Gradle module AppComponent appComponent = ((MyApplication) getApplicationContext()).appComponent; // Creates a new instance of LoginComponent // Injects the component to populate the @Inject fields DaggerLoginComponent.factory().create(appComponent).inject(this); // Now you can access loginViewModel } }
LoginViewModel, UserRepository metriğine bağlıdır; ve LoginComponent için
AppComponent üzerinden erişebiliyorsa, AppComponent tarafından şurada kullanıma sunulması gerekir:
arayüzü:
Kotlin
@Singleton @Component interface AppComponent { fun userRepository(): UserRepository }
Java
@Singleton @Component public interface AppComponent { UserRepository userRepository(); }
Bağımlı bileşenlere sahip kapsam kuralları,
alt bileşenlerde bulunur. LoginComponent, AppComponent öğesinin bir örneğini kullandığından,
aynı kapsam ek açıklamasını kullanamazlar.
LoginViewModel kapsamını LoginComponent kapsamına almak isterseniz bunu şu şekilde yaparsınız:
özel @ActivityScope ek açıklamasını kullanıyor.
Kotlin
@ActivityScope @Component(dependencies = [AppComponent::class]) interface LoginComponent { ... } @ActivityScope class LoginViewModel @Inject constructor( private val userRepository: UserRepository ) { ... }
Java
@ActivityScope @Component(dependencies = AppComponent.class) public interface LoginComponent { ... } @ActivityScope public class LoginViewModel { private final UserRepository userRepository; @Inject public LoginViewModel(UserRepository userRepository) { this.userRepository = userRepository; } }
En iyi uygulamalar
ApplicationComponent, her zamanappmodülünde olmalıdır.Alan yerleştirme işlemi gerçekleştirmeniz gerekiyorsa modüllerde Dagger bileşenleri oluşturma veya nesnelerinizin belirli bir akışı için en iyi yoludur.
Yardımcı program veya yardımcı olması amaçlanan ve ihtiyacınız olmayan Gradle modülleri için için bir grafik oluşturmak (bu nedenle bir Dagger bileşenine ihtiyacınız vardır), Herkese açık olan ve @Provides ve @Binds yöntemlerine sahip bu sınıfların oluşturucu yerleştirmeyi desteklemez.
Dagger'ı özellik modülleriyle bir Android uygulamasında kullanmak için bileşen tarafından sağlanan bağımlılıklara erişebilmek için ihtiyaç
appmodülündeApplicationComponenttanımlandı.