在ViewPager内部的片段之间传递参数

时间:2019-06-24 05:14:49

标签: android android-fragments kotlin android-viewpager fragment

我正在使用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的viewpager中使用该适配器

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

滑动到下一页

问题

现在,问题在于,应用启动时,会立即执行 FragmentB 中的 getArguments ,但我什至还没有刷过它,或者从中传递了参数> FragmentA ,并为 getArguments 生成空值。

使用上面的代码,我认为从 FragmentA 按下fab按钮后,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")返回null

2 个答案:

答案 0 :(得分:1)

我认为您应该使用默认的“工厂方法”模板。创建Fragment时选中这些复选框 Check these checkbox when you creating a <code>Fragment</code>

之后,您可以看到带有构造函数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)
    }
}

现在您可以拥有这些值param1param2

如果要使用构造方法:

public class BlankFragment extends Fragment {

  public BlankFragment()
  {} // Empty Constructor required

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

这也可以,但是您将有2个构造函数,而您只能使用一种工厂方法(并且它是由AndroidStudio自动生成的!)

答案 1 :(得分:1)

推荐的简单解决方案是使用View Model guide中所述的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内部的所有片段之间共享。