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.
Ö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:
LoginActivityComponent
iş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.
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 zamanapp
modü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ç
app
modülündeApplicationComponent
tanımlandı.