保存ViewPager中嵌套片段的状态

时间:2018-05-17 09:25:05

标签: android android-fragments kotlin

所以我有一个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(列表)。每次切换到Fragment 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()
        }
    }

2 个答案:

答案 0 :(得分:0)

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

  

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

为什么这样工作?您的应用程序并不知道您想要打开旧片段而不是创建新片段(因为您实际上要求创建新片段)。此外,你必须告诉你的申请 - "恩,你!不要创建新片段,但如果有任何"则从后台获取旧片段。

你可以查看如何做到这一点。在这里:How to resume Fragment from BackStack if exists

PS:不是通过构造函数创建片段的好习惯,而是通过静态方法" getInstance():Fragment"。

答案 1 :(得分:0)

所以我设法通过使用片段"缓存":

解决了这个问题
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()
    }

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