[英]Saving state of nested fragments that are in ViewPager
所以我有一个DrawerLayout活动。 我可以切换到包含TabLayout的Fragment1
以及其他三个片段( NestedFragment1
, NestedFragment2
和NestedFragment3
)。 我希望能够在每个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.