首页 > 解决方案 > 保存 ViewPager 中嵌套片段的状态

问题描述

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

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()

    }
}

我想保存forecastListperformQuery方法返回的(列表)。每次我切换到片段 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()
        }
    }

标签: androidandroid-fragmentskotlin

解决方案


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

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()
    }

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


推荐阅读