Данная статья является седьмой частью серии статей, предназначенных, по словам автора, для тех, кто не может разобраться с внедрением зависимостей и фреймворком Dagger 2, либо только собирается это сделать. Оригинал написан 30 декабря 2017 года. Перевод вольный.
Это седьмая статья цикла «Dagger 2 для начинающих Android разработчиков.». Если вы не читали предыдущие, то вам сюда.
@Scope
для создания объектов в единственном экземпляре (singleton). @Named
для разделения методов, предоставляющих объекты одинакового типа. @Qualifier
как альтернативу @Named
.Component
Activity
? Activity
создается и уничтожается в своем жизненном цикле, а что происходит с зависимостями? Зависимости, созданные внутри Activity
уничтожаются вместе с Activity
.MainActivity
как отдельный объект и создадим для него свой модуль и компонент.Dagger2Part2
.Activity
MainActivityFeature
. MainActivity
.@Scope
public @interface MainActivityScope {}
MainActivity
MainActivity
и пометим его только что созданной аннотацией.@Component(dependencies = RandomUserComponent.class)
@MainActivityScope
public interface MainActivityComponent {
RandomUserAdapter getRandomUserAdapter();
RandomUsersApi getRandomUserService();
}
MainActivityComponent
ссылаться на RandomUserComponent
, для чего используется атрибут dependencies
. Другими словами, этот атрибут говорит Dagger 2 обращаться к RandomUserComponent
, если требуются дополнительные зависимости.Activity
нам потребуются адаптер для API и объект для создания вызовов к RandomUsersAPI
. Следовательно, реализуем методы getRandomUserAdapter()
и getRandomUserService()
.MainActivity
@Module
public class MainActivityModule {
private final MainActivity mainActivity;
public MainActivityModule(MainActivity mainActivity) {
this.mainActivity = mainActivity;
}
@Provides
@MainActivityScope
public RandomUserAdapter randomUserAdapter(Picasso picasso){
return new RandomUserAdapter(mainActivity, picasso);
}
}
MainActivity
через адаптер не обязательно, я сделал это для примера. Если нужен контекст для Picasso
, то можно использовать holder.imageView.getContext()
.@MainActivityScope
, которая добавлена к методу randomUserAdapter()
чтобы ограничить область использования зависимости уровнем Activity
.modules
.@Component(modules = MainActivityModule.class, dependencies = RandomUserComponent.class)
@MainActivityScope
public interface MainActivityComponent {
RandomUserAdapter getRandomUserAdapter();
RandomUsersApi getRandomUserService();
}
Application
public class RandomUserApplication extends Application {
// добавьте имя этого класса в манифест
private RandomUserComponent randomUserApplicationComponent;
public static RandomUserApplication get(Activity activity){
return (RandomUserApplication) activity.getApplication();
}
@Override
public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree());
randomUserApplicationComponent = DaggerRandomUserComponent.builder()
.contextModule(new ContextModule(this))
.build();
}
public RandomUserComponent getRandomUserApplicationComponent(){
return randomUserApplicationComponent;
}
Application
, содержит все зависимости уровня приложения — RandomUserApplicationComponent
.MainActivity
DaggerMainActivityComponent
. Для использования зависимостей уровня Activity
нам понадобится получить некоторые зависимости уровня приложения.public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
....
MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
.mainActivityModule(new MainActivityModule(this))
.randomUserComponent(RandomUserApplication.get(this).getRandomUserApplicationComponent())
.build();
randomUsersApi = mainActivityComponent.getRandomUserService();
mAdapter = mainActivityComponent.getRandomUserAdapter();
....
}
}
afterActivityLevelComponent()
в ветке с проектом.Activity
. Поздравьте себя.randomUserApi = mainActivityComponent.getRandomUserService();
mAdapter = mainActivityComponent.getRandomUserAdapter();
…
@Inject
RandomUserService
и RandomUserAdapter
, пусть Dagger 2 обрабатывает поле, которые мы пометим аннотацией @Inject
.@Inject
в кратчайшие сроки. Полный пример вы можете просмотреть в следующей ветке.MainActivityComponent
getRandomUserService()
и getRandomUserAdapter()
и добавим метод для внедрения MainActivity
.@Component(modules = MainActivityModule.class, dependencies = RandomUserComponent.class)
@MainActivityScope
public interface MainActivityComponent {
void injectMainActivity(MainActivity mainActivity);
}
MainActivity
public class MainActivity extends AppCompatActivity {
....
@Inject
RandomUsersApi randomUsersApi;
@Inject
RandomUserAdapter mAdapter;
....
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.....
MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
.mainActivityModule(new MainActivityModule(this))
.randomUserComponent(RandomUserApplication.get(this).getRandomUserApplicationComponent())
.build();
mainActivityComponent.injectMainActivity(this);
....
}
}
void
) он понимает, что должно быть что-то, что ему нужно в классе, то есть он будет инициализировать в классе поля, помеченные аннотацией @Inject
.Activity
. Также увидели пример использования аннотации @Inject
.К сожалению, не доступен сервер mySQL