У меня есть Фрагмент Android, который вводит модель привязки данных. более конкретно, я добавляю ViewModel (определенный в XML-фрагменте фрагмента через тег) и вызываю ViewDataBinding.setViewModel(), чтобы инициировать привязку в onCreateView().Фрагмент Android с сохраненнымInstanceState безпараллельный Dagger2 инъецированная модель с впрыском конструктора
Фрагмент вводится в действие посредством инъекции поля, а ViewModel вводится в Фрагмент также посредством инъекции поля. однако сам ViewModel вводит свои зависимости через инъекцию конструктора.
Это работает отлично, когда первый экземпляр фрагментации --- когда savedInstanceState имеет значение null. однако он не работает, когда восстанавливается Фрагмент: в настоящее время ViewModel имеет значение null, потому что я не разделял его, когда состояние фрагмента сохраняется.
Сохранение состояния ViewModel не должно быть проблемой, но я с трудом вижу, как его восстановить позже. состояние будет находиться в Посылке, но не в зависимостях (конструкторах).
В качестве примера рассмотрим простую форму входа, содержащую два поля, имя пользователя и пароль. состояние LoginViewModel - это просто две строки, но также имеет различные зависимости для соответствующих обязанностей. ниже я предоставляю приведенный пример кода для Activity, Fragment и ViewModel.
пока что я не предоставил никаких средств для сохранения состояния ViewModel при сохранении фрагмента. Я работал над этим, имея базовый Parcelable pattern, когда понял, что концептуально я не видел, как вводить зависимости ViewModel. при восстановлении ViewModel через интерфейс Parcel - особенно интерфейс Parcelable.Creator <>, похоже, мне нужно напрямую создать экземпляр MyModelModel. однако этот объект обычно вводится и, что более важно, его зависимости вводятся в конструкторе.
Это похоже на конкретный случай Android, который на самом деле является более общим кейсом Dagger2: инъецируемый объект иногда восстанавливается из сохраненного состояния, но все еще нуждается в его зависимостях, вводимых через конструктор.
вот LoginActivity ...
public class LoginActivity extends Activity {
@Inject /* default */ Lazy<LoginFragment> loginFragment;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_activity);
ActivityComponent.Creator.create(getAppComponent(), this).inject(this);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, loginFragment.get())
.commit();
}
}
}
вот LoginFragment ...
public class LoginFragment extends Fragment {
@Inject /* default */ LoginViewModel loginViewModel;
@Nullable
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final LoginFragmentBinding binding = setViewDataBinding(LoginFragmentBinding.inflate(inflater, container, false));
binding.setViewModel(loginViewModel);
// ... call a few methods on loginViewModel
return binding.getRoot();
}
}
и, наконец, вот отведенной версия LoginViewModel ...
public class LoginViewModel {
private final Dependency dep;
private String userName;
private String password;
@Inject
public LoginViewModel(final Dependency dep) {
this.dep = dep;
}
@Bindable
public String getUserName() {
return userName;
}
public void setUserName(final String userName) {
this.userName = userName;
notifyPropertyChanged(BR.userName);
}
// ... getter/setter for password
}
Если ответ был полезным, ты не против принятия Это? –