Отправка данных из вложенных фрагментов в родительский фрагмент
у меня есть Fragment FR1, который содержит несколько Nested Fragments; FRa, FRb, FRc. Эти Nested Fragments изменяются нажатием кнопки Buttons on FR1's макет. Каждый из Nested Fragments имеют несколько полей ввода внутри них; которые включают такие вещи, как EditTexts, NumberPickers и Spinners. Когда мой пользователь проходит и заполняет все значения Nested Fragments, FR1 (Родительский фрагмент) имеет кнопку отправки.
как я могу тогда, извлеките мои значения из my Nested Fragments и привести их в FR1.
- все Viewsобъявляются и программно обрабатываются в каждомNestedFragment.
- родитель Fragment,FR1обрабатывает транзакцииNestedFragments.
я надеюсь, что этот вопрос достаточно ясен, и я не уверен, что код необходим для публикации, но если кто-то чувствует иначе, я могу это сделать.
изменить 1:
вот как я добавляю мой Nested Fragments:
tempRangeButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getChildFragmentManager().beginTransaction()
                    .add(R.id.settings_fragment_tertiary_nest, tempFrag)
                    .commit();
        }
    });
    scheduleButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getChildFragmentManager().beginTransaction()
                    .add(R.id.settings_fragment_tertiary_nest, scheduleFrag)
                    .commit();
        }
    });
    alertsButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getChildFragmentManager().beginTransaction()
                    .add(R.id.settings_fragment_tertiary_nest, alertsFrag)
                    .commit();
        }
    });
    submitProfile.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            constructNewProfile();
        }
    });
где мой constructNewProfile() метод нуждается в значениях из my Nested Fragments.
public Fragment tempFrag = fragment_profile_settings_temperature
        .newInstance();
public Fragment scheduleFrag= fragment_profile_settings_schedules
            .newInstance();
public Fragment alertsFrag = fragment_profile_settings_alerts
        .newInstance();
вышесказанное относится к полям родительского фрагмента; и как они изначально создаются.
6 ответов
лучший способ - использовать интерфейс:
- 
объявить интерфейс во фрагменте гнезда // Container Activity or Fragment must implement this interface public interface OnPlayerSelectionSetListener { public void onPlayerSelectionSet(List<Player> players_ist); }
- 
прикрепите интерфейс к родительскому фрагменту // In the child fragment. public void onAttachToParentFragment(Fragment fragment) { try { mOnPlayerSelectionSetListener = (OnPlayerSelectionSetListener)fragment; } catch (ClassCastException e) { throw new ClassCastException( fragment.toString() + " must implement OnPlayerSelectionSetListener"); } } @Override public void onCreate(Bundle savedInstanceState) { Log.i(TAG, "onCreate"); super.onCreate(savedInstanceState); onAttachToParentFragment(getParentFragment()); // ... }
- 
звонок слушателя на кнопку нажать. // In the child fragment. @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_submit: if (mOnPlayerSelectionSetListener != null) { mOnPlayerSelectionSetListener.onPlayerSelectionSet(selectedPlayers); } break; } }
- 
пусть ваш родительский фрагмент реализует интерфейс. public class Fragment_Parent extends Fragment implements Nested_Fragment.OnPlayerSelectionSetListener { // ... @Override public void onPlayerSelectionSet(final List<Player> players_list) { FragmentManager fragmentManager = getChildFragmentManager(); SomeOtherNestFrag someOtherNestFrag = (SomeOtherNestFrag)fragmentManager.findFragmentByTag("Some fragment tag"); //Tag of your fragment which you should use when you add if(someOtherNestFrag != null) { // your some other frag need to provide some data back based on views. SomeData somedata = someOtherNestFrag.getSomeData(); // it can be a string, or int, or some custom java object. } } }
добавить тег, когда вы делаете фрагмент транзакции, так что вы можете посмотреть его затем вызвать его метод. FragmentTransaction
это правильный способ обработки связи между фрагментом и фрагментом гнезда, это почти то же самое для активности и фрагмента. http://developer.android.com/guide/components/fragments.html#EventCallbacks
на самом деле есть еще один официальный способ, он использует результат деятельности, но этот достаточно хорош и распространен.
вместо использования интерфейса вы можете вызвать дочерний фрагмент ниже:
( (YourFragmentName) getParentFragment() ).yourMethodName();
можно использовать getChildFragmentManager() и найти вложенные фрагменты, получить их и запустить некоторые методы для получения входных значений
проверить instanceOf перед получением родительского фрагмента, который лучше:
if (getParentFragment() instanceof ParentFragmentName) {
  getParentFragment().Your_parent_fragment_method();
}
лучший способ передачи данных между фрагментами - использовать интерфейс. Вот что тебе нужно сделать.: В вас вложен фрагмент:
public interface OnDataPass {
    public void OnDataPass(int i);
}
OnDataPass dataPasser;
@Override
public void onAttach(Activity a) {
    super.onAttach(a);
    dataPasser = (OnDataPass) a;
}
public void passData(int i) {
    dataPasser.OnDataPass(i);
}
в Родительском фрагменте:
public class Fragment_Parent extends Fragment implements OnDataPass {
...
    @Override
    public void OnDataPass(int i) {
        this.input = i;
    }
    btnOk.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Fragment fragment = getSupportFragmentManager().findFragmentByTag("0");
            ((Fragment_Fr1) fragment).passData();
        }
    }
}
вы можете использовать обмен данными между фрагментами.
public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
    public void select(Item item) {
        selected.setValue(item);
    }
    public LiveData<Item> getSelected() {
        return selected;
    }
}
public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}
public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, item -> {
           // Update the UI.
        });
    }
}
Подробнее Архитектура ViewModel
