Почему я хочу избегать конструкторов не по умолчанию в фрагментах?
Я создаю приложение с Fragments
, и в одном из них я создал конструктор, отличный от стандартного, и получил это предупреждение:
Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead
Может кто-нибудь сказать мне, почему это не очень хорошая идея?
Можете ли вы также предложить, как бы я это сделал:
public static class MenuFragment extends ListFragment {
public ListView listView1;
Categories category;
//this is my "non-default" constructor
public MenuFragment(Categories category){
this.category = category;
}....
Без использования конструктора, отличного от стандартного?
Ответы
Ответ 1
Сделайте объект пакета и вставьте свои данные (в этом примере ваш объект Category
). Будьте осторожны, вы не можете передать этот объект прямо в комплект, если он не сериализуется.
Я думаю, что лучше построить свой объект во фрагменте и поместить в комплект только идентификатор или что-то еще. Это код для создания и присоединения пакета:
Bundle args = new Bundle();
args.putLong("key", value);
yourFragment.setArguments(args);
После этого в данных доступа к фрагменту:
Type value = getArguments().getType("key");
Что все.
Ответ 2
Кажется, что ни один из ответов на самом деле не отвечает "зачем использовать пакет для передачи параметров, а не нестандартных конструкторов"
Причина, по которой вы должны передавать параметры через пакет, заключается в том, что когда система восстанавливает fragment
(например, при изменении конфигурации), она автоматически восстанавливает ваш bundle
.
Обратные вызовы, такие как onCreate
или onCreateView
, должны читать параметры из bundle
- таким образом вы гарантированно вернете состояние fragment
правильно в том же состоянии, в котором был инициализирован fragment
с ( обратите внимание, что это состояние может отличаться от onSaveInstanceState bundle
, которое передается в onCreate/onCreateView
)
Рекомендация использования статического метода newInstance()
является лишь рекомендацией. Вы можете использовать конструктор не по умолчанию, но убедитесь, что вы заполняете параметры инициализации в bundle
внутри тела этого конструктора. И прочитайте эти параметры в методах onCreate()
или onCreateView()
.
Ответ 3
В вашем Fragment
не должно быть конструкторов из-за того, как FragmentManager
создает экземпляр.
У вас должен быть статический метод newInstance()
, определенный с параметрами, которые вам нужны, а затем свяжите их и установите в качестве аргументов фрагмента, доступ к которому вы можете получить позже с параметром Bundle
.
Например:
public static MyFragment newInstance(int title, String message) {
MyFragment fragment = new MyFragment();
Bundle bundle = new Bundle(2);
bundle.putInt(EXTRA_TITLE, title);
bundle.putString(EXTRA_MESSAGE, message);
fragment.setArguments(bundle);
return fragment ;
}
И прочитайте эти аргументы в onCreate
:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
title = getArguments().getInt(EXTRA_TITLE);
message = getArguments().getString(EXTRA_MESSAGE);
//...
}
Таким образом, если он отсоединен и повторно подключен, состояние объекта может быть сохранено через аргументы, похожие на bundles
, прикрепленные к Intent
s.
Ответ 4
Если вы используете параметр для некоторого класса. попробуйте это
SomeClass mSomeInstance;
public static final MyFragment newInstance(SomeClass someInstance){
MyFragment f = new MyFragment();
f.mSomeInstance = someInstance;
return f;
}
Ответ 5
Я использовал метод, и он работает!
public FragmentHome() {
// Required empty public constructor
}
public void FragmentHomeConstructor(Context context, String stringBundle) {
mContext = context;
mStringBundle = stringBundle;
}
Сделайте это методом фрагмента oncreate(), чтобы получить контекст без каких-либо ошибок!
mContext = this.getActivity();
В oncreate()
метод вашей деятельности:
FragmentHome fragmentHome = new FragmentHome();
fragmentHome.FragmentHomeConstructor(mContext, mStringBundle);
Ответ 6
Я думаю, нет никакой разницы между статическим конструктором и двумя конструкторами (пустым и параметризованным, который хранит аргументы в комплекте с фрагментами фрагментов), скорее всего, это эмпирическое правило создается, чтобы уменьшить вероятность забыть реализовать no-arg конструктор в Java, который неявно генерируется при наличии перегрузки.
В моих проектах я использую Kotlin и реализую фрагменты с первичным конструктором no-arg и вторичным конструктором для аргументов, которые просто хранят их в комплекте и задают в качестве аргументов фрагмента, все работает нормально.