Иногда, когда мы изучаем структуру инъекции зависимостей, как Dagger 2, неправильное представление может возникнуть, что new
ключевых слов и статические фабрики следует избегать любой ценой, и что каждый объект должен быть введен.
В случае фрагментов best practice для создания экземпляров должен использовать статические методы фабрики. Несмотря на то, что предыдущая структура DI, Roboguice, поощряла инъекцию фрагментов в качестве свойств Activity (@Inject MeasurementFragment mf
), с Dagger 2, может быть, лучше попробовать другой подход. Причиной этого является то, что нам необходимо согласовать с FragmentManager
для деятельности:
Для данного действия Фрагменты обрабатываются . Когда вызывается Activity onSaveInstanceState(Bundle outBundle)
(например, в условиях низкой памяти), FragmentManager
сохранит состояние экземпляра каждого фрагмента для восстановления внутри onCreate(Bundle savedInstanceState);
.
Вот почему вы часто видите в Android примеры:
if (savedInstanceState == null) {
// During initial setup, plug in the details fragment.
DetailsFragment details = new DetailsFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
}
Проверка на saveInstanceState == null
в случае фрагмента уже присутствует в FragmentManager. В случае восстановления Деятельности из сохраненного состояния экземпляра вы можете использовать:
fragmentManager.findFragmentByTag(String tag)
, чтобы получить ручку на нем. Это означает, что простая инъекция свойств фрагмента внутри операции с использованием кинжала 2 недостаточна для учета сложных жизненных циклов фрагментов и видов деятельности.
Лучшим подходом может стать отказ от инъекции вашего фрагмента внутри вашей деятельности и использование статических фабрик, как рекомендовано в Руководстве разработчика. Затем вы введете зависимости для вашего фрагмента внутри самого фрагмента.Что-то вроде этого:
class MeasurementFragment extends Fragment {
@Inject Converter converter;
static MeasurementFragment instantiate() {
//if MeasurementFragment comes to require params in the future
//you can pass them in here and use setArguments(Bundle params);
return new MeasurementFragment(null);
}
MeasurementFragment(){
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
DaggerMainActivityComponent.builder()
.build()
.inject(this);
}
}
Теперь, когда вы используете fragmentManager.beginTransaction().add()
на MeasurementFragment
внутри вашей деятельности, инъекции будут выполняться на коммит, когда Android система применит жизненным циклом обратных вызовов до onActivityCreated(Bundle bundle)
.
Вот что ваша активность может выглядеть с таким подходом:
class MainActivity extends AppCompatActivity {
public static final String MEASUREMENT_FRAG = "MEASUREMENT_FRAG";
MeasurementFragment measureFrag;
@Override
protected void OnCreate(Bundle b){
super(b);
injectMembers();
if (b == null) {
measureFrag = MeasurementFragment.instantiate();
getFragmentManager().beginTransaction().add(R.id.frag_container, measureFrag, MEASUREMENT_FRAG).commit();
}
else {
//frag is already instantiated and added to container
measureFrag = getFragmentManager().findFragmentByTag(MEASUREMENT_FRAG);
}
}
@VisibleForTesting
void injectMembers() {
DaggerMainActivityComponent().create().inject(this);
}
}
То, что я изложил здесь подход к инъекциям членов внутри фрагментов, что демонстрируется в этом Dagger 2 example on Github. Еще один шаг заключается в том, чтобы сделать Фрагменты максимально легкими и полностью избегать инъекции зависимостей внутри них, как показано в Google Android Architecture Blueprint for Dagger 2.
Вы должны ввести MeasurementFragment в график зависимостей в [3]. Я думаю, что это единственный способ. Для части дизайна вы можете создать объект DaggerMainActivityComponent в MainActivity, затем получить доступ и вставить его в фрагмент, используя getter и setter. –
Попробуйте добавить конструктор по умолчанию для MeasurementFragment, аннотированный с помощью Inject. Удалите введенный void (MeasurementFragment mf); от вашего компонента и ваш метод Предоставление метода MeasurementFragment из вашего модуля. – ootinii