繁体   English   中英

保存ViewPager中嵌套片段的状态

[英]Saving state of nested fragments that are in ViewPager

所以我有一个DrawerLayout活动。 我可以切换到包含TabLayout的Fragment1以及其他三个片段( NestedFragment1NestedFragment2NestedFragment3 )。 我希望能够在每个NestedFragments中保存数据,因为我在其中进行了API调用。 我尝试覆盖onSaveInstanceState并保存数据,但SavedInstanceState始终为null。

Fragment1代码:

    class Fragment1 : Fragment() {
        private lateinit var viewPager: ViewPager
        private lateinit var tabLayout: TabLayout
        private lateinit var pagerAdapter: PagerAdapter

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            pagerAdapter = ForecastPagerAdapter(childFragmentManager)

        }

        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View? {
            val view = inflater.inflate(R.layout.fragment_forecast, container, false)
            viewPager = view.findViewById(R.id.view_pager)
            viewPager.offscreenPageLimit = 3
            viewPager.adapter = pagerAdapter
            tabLayout = view.findViewById(R.id.tabs)
            tabLayout.setupWithViewPager(viewPager)
            return view
        }
}

Example of nested fragment code:

    class NestedFragment : Fragment() {

        private lateinit var recyclerView: RecyclerView
        private lateinit var recyclerViewAdapter: HourForecastAdapter
        private lateinit var swipeRefreshLayout: SwipeRefreshLayout

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)

            recyclerViewAdapter = HourForecastAdapter()


        }

        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            val view = inflater!!.inflate(R.layout.fragment_day_forecast, container, false)

            swipeRefreshLayout = view.findViewById(R.id.swipe_refresh_layout_hour)
            swipeRefreshLayout.apply {
                this.setOnRefreshListener {
                    performQuery()
                }
            }
            recyclerView = view.findViewById(R.id.recycler_view_hour_forecast)
            recyclerView.adapter = recyclerViewAdapter
            recyclerView.layoutManager = LinearLayoutManager(activity)


            return view
        }

 fun performQuery() {
        // ...

                    recyclerViewAdapter.forecastList = result.hourly.data
                    recyclerViewAdapter.notifyDataSetChanged()

    }
}

我想保存forecastList这是由返回(列表) performQuery方法。 每次切换到片段1时,嵌套片段中的所有数据都将消失。

这是用于切换片段的代码:

navigationView.setNavigationItemSelectedListener {
                var fragment = when (it.itemId) {
                    R.id.nav_map -> Fragment0()
                    R.id.nav_forecast -> Fragment1()
                    R.id.nav_app_info -> Fragment2()
                    else -> Fragment1()
                }

                replaceFragment()

                it.isChecked = true
                drawerLayout.closeDrawers()
                true
            }
        }

编辑:添加了片段替换功能:

fun replaceFragment(fragment: android.support.v4.app.Fragment){
        val fragmentName = fragment::class.java.simpleName
        val isFragmentInBackStack = fragmentManager.popBackStackImmediate(fragmentName, 0)
        if (!isFragmentInBackStack) {
            fragmentManager.beginTransaction()
                    .replace(R.id.main_activity_frame, fragment)
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                    .addToBackStack(fragmentName)
                    .commit()
        }
    }

首先,在提交事务之前,必须调用.addToBackstack(null) 这也会影响您的后退按钮。 请参阅#documentation:

将此事务添加到后台堆栈。 这意味着该事务在提交后将被记住,并在以后从堆栈中弹出时撤消其操作。

为什么这样工作? 您的应用程序不知道您要打开旧片段而不是创建新片段(因为您实际上要求创建新片段)。 另外,您还必须告诉您的应用程序:“是的,您!不要创建新的片段,但是如果有的话,请从后台获取旧的片段”。

您可以检查如何做fe。 此处: 如何从BackStack恢复片段(如果存在)

PS:最好不要通过构造器来创建片段,而是通过静态方法“ getInstance():Fragment”来创建片段。

所以我设法通过使用片段“缓存”解决了这个问题:

fun cacheFragment(fragment: android.support.v4.app.Fragment) {
        Log.d("Caching", "Working with ${fragment.javaClass.simpleName}")
        var findFragment = supportFragmentManager.findFragmentByTag(fragment.javaClass.simpleName)
        if (findFragment == null) {
            Log.d("Caching", "Creating new instance of ${fragment.javaClass.simpleName}")
            findFragment = fragment.javaClass.newInstance()
        }
        supportFragmentManager.beginTransaction()
                .replace(R.id.main_activity_frame, findFragment, fragment.javaClass.simpleName)
                .addToBackStack(null)
                .commit()
    }

当用户从导航栏中选择一个项目时,我们检查片段是否已存在于后堆栈中,然后可以重复使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM