Передача аргументов между фрагментами, которые находятся внутри ViewPager - PullRequest
0 голосов
/ 24 июня 2019

Я работаю с различными фрагментами, размещенными на ViewPager.

Основная цель этого состоит в том, что мне нужно преобразовать бумажную форму в цифровую форму, и в удобных для пользователя целях я решил позволить пользователю пролистывать все фрагменты и заполнять каждый из них до конца. форма.

Моя цель состоит в том, чтобы создать объект в конце последнего фрагмента, поэтому в это время у меня будут все данные, поступающие из следующих фрагментов.

Я исследовал и обнаружил, что могу использовать setArguments() для передачи пакета данных от каждого фрагмента до следующего до конца, и это отличная идея, поскольку, если пользователь хочет вернуться, он может изменить некоторые аргументы и продолжайте процесс считывания до конца, и у последнего фрагмента у меня будут все аргументы из всех фрагментов для создания уникального объекта, содержащего все данные, представляющие всю форму.

Это то, что я пробовал

Сначала я создал простой ViewPager адаптер для переключения между различными фрагментами при перелистывании

MyPagerAdapter

class MyPagerAdapter(fm:FragmentManager): FragmentStatePagerAdapter(fm) {

    override fun getItem(position: Int): Fragment {
        return when(position){
            0 -> FragmentA.newInstance()
            1 -> FragmentB.newInstance()
            2 -> FragmentC.newInstance()
            else -> {
                FragmentA()
            }
        }
    }

    override fun getCount(): Int {
        return 3
    }
}

Тогда я просто использую этот адаптер с моим пейджером на MainActivity

MainActivity

class MainActivity : FragmentActivity(), MainContract.MainView {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setupViewPager()
    }

    override fun setupViewPager() {
        viewPager.adapter = MyPagerAdapter(supportFragmentManager)
        viewPager.disableScroll(true)
        selectIndex(0)
    }

    override fun selectIndex(newIndex: Int) {
        viewPager.currentItem = newIndex
    }

    override fun getFragment(position: Int): Fragment {
        return MyPagerAdapter(supportFragmentManager).getItem(position)
    }

}

И здесь мне нужно передать аргументы от FragmentA до FragmentB

Fragmenta

class FragmentA : Fragment() {

    companion object {
        fun newInstance(): FragmentA = FragmentA()
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_A, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        fab_continue.setOnClickListener {

            val name = etxt_name.text.toString().trim()
            val phone = etxt_phone.text.toString().trim()

            val bundle = Bundle()
            bundle.putString("name",name)
            bundle.putString("phone",phone)

            (activity as MainActivity).getFragment(1).arguments = bundle
            (activity as MainActivity).selectIndex(1)
        }

    }

Здесь я полагаю, что

(activity as MainActivity).getFragment(1).arguments = bundle

получает и раздувает следующий фрагмент, этот фрагмент равен FragmentB и передает ему аргументы

Пока

(activity as MainActivity).selectIndex(1)

Просто проведите пальцем до следующей страницы с FragmentB

Проблема

Теперь проблема в том, что при запуске приложения getArguments из FragmentB выполняется немедленно, но я даже не проводил по нему пальцем или не передавал аргументы из FragmentA , и это создает ноль для getArguments .

Используя приведенный выше код, я подумал, что после нажатия моей потрясающей кнопки с FragmentA метод getFragment(1) создаст экземпляр моего FragmentB , но, похоже, не делает это должно сделать.

Так у меня FragmentB

class FragmentB: Fragment() {

    companion object {
        fun newInstance(): FragmentB = FragmentB()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d("Argumentos:",""+arguments?.getString("name")) //This returns null
    }

arguments?.getString("name") возвращает ноль

Ответы [ 2 ]

1 голос
/ 26 июня 2019

Рекомендуемое и простое решение - использование ViewModel, как описано в Просмотр руководства по моделям .Что-то нравится:

MyViewModel model = ViewModelProviders.of(yourActivity).get(MyViewModel.class); // in your activity
// in your fragments
model = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
model.yourFunctionToChangeData(yourData);
// observer result in other fragments
model.getSelected().observe(this, { yourData ->
       // Update the UI.
    });

Используя ViewModel, модель создается один раз в Activity и распределяется между всеми вашими фрагментами внутри Activity.

1 голос
/ 24 июня 2019

Я думаю, вы должны использовать шаблон Factory Method по умолчанию.Установите этот флажок при создании Fragment imageFragment">

. После этого вы можете увидеть шаблон с конструктором newInstance()

создать фрагмент в действиикак это

    BlankFragment.newInstance("First Thing", "Second String")

, а для Fragment пути доступа генерируются

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    arguments?.let {
        param1 = it.getString(ARG_PARAM1) 
        param2 = it.getString(ARG_PARAM2)
    }
}

, теперь вы можете иметь эти значения param1 и param2.

Если вы хотите использовать путь конструктора:

public class BlankFragment extends Fragment {

  public BlankFragment()
  {} // Empty Constructor required

  public BlankFragment(int someParam)
  {
     // your constructor
  }
}

Это также работает, но у вас будет 2 конструктора, в то время как вы можете использовать только один метод фабрики (и он автоматически генерируется AndroidStudio!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...