【问题标题】:Passing arguments between Fragments that are inside a ViewPager在 ViewPager 内的 Fragment 之间传递参数
【发布时间】:2019-06-24 05:14:49
【问题描述】:

我正在处理由 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 一起使用

主要活动

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

的地方

片段A

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 生成 null。

使用上面的代码,我认为从 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

【问题讨论】:

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


    【解决方案1】:

    我认为您应该使用默认的工厂方法模板。创建Fragment 时选中这些复选框

    之后可以看到带有构造函数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 自动生成的!)

    【讨论】:

    • 但是没有办法按照我的方式去做吗?我认为工厂与我拥有的工厂相同,只是将参数设置为新实例
    • 您也可以在构造函数中传递这些值。那么它应该看起来像FragmentB("String1")
    • 感谢您的回复我终于在没有查看器的情况下解决了它并实现了每个片段的片段膨胀,谢谢
    【解决方案2】:

    推荐的简单解决方案是使用ViewModel,如View Model guide 中所述。喜欢的东西:

    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 内的所有片段之间共享。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 2016-03-25
      相关资源
      最近更新 更多