所以我有一个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
(列表)。每次切换到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()
}
}
答案 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()
}
当用户从导航栏中选择一个项目时,我们会检查该片段是否已存在于后台堆栈中,然后我们可以重复使用它。