标题本身就是我的问题,每当我打开MainActivity,然后导航到汉堡包/抽屉菜单中可用的另一个片段,然后按/刷回以返回它重新创建的主屏幕(第一个片段)。导航组件有没有办法使其不重新创建第一个片段?我正在使用Android Studio生成的Jetpack导航模板,这似乎是默认行为。
这是主要活动
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private var _binding: ActivityMainBinding? = null
// This property is only valid between onCreate and
// onDestroyView.
private val binding get() = _binding!!
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.appBarMain.toolbar)
drawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_content_main)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home, R.id.nav_marketcap, R.id.nav_about), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
menu.findItem(R.id.action_settings).isChecked = AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_main)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
override fun onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START)
else
super.onBackPressed()
}
}
这是主片段(主活动中的第一个片段),其中包含子片段Asset片段
class HomeFragment : Fragment() {
private val homeViewModel: HomeViewModel by activityViewModels()
private var _binding: FragmentHomeBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private lateinit var viewPager : ViewPager2
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
viewPager = binding.viewPagerContainer
val bottomNav = binding.bottomNav
// val tabLayout = binding.tabLayout
val fragmentList : MutableList<Pair<String, Fragment>> = mutableListOf()
fragmentList.add(Pair(getString(R.string.assets), AssetFragment.newInstance()))
fragmentList.add(Pair(getString(R.string.news), NewsFragment.newInstance()))
fragmentList.add(Pair(getString(R.string.videos), VideosFragment.newInstance()))
val adapter = AppFragmentAdapter(fragmentList, this)
viewPager.adapter = adapter
viewPager.offscreenPageLimit = 2
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
bottomNav.menu.getItem(position).isChecked = true
homeViewModel.setTitle(adapter.getFragmentTabName(position))
}
})
val bottomNavListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when(item.itemId) {
R.id.page_1 -> {
// Respond to navigation item 1 click
viewPager.setCurrentItem(0, true)
true
}
R.id.page_2 -> {
// Respond to navigation item 2 click
viewPager.setCurrentItem(1, true)
true
}
R.id.page_3 -> {
// Respond to navigation item 3 click
viewPager.setCurrentItem(2, true)
true
}
else -> false
}
}
bottomNav.setOnNavigationItemSelectedListener(bottomNavListener)
// val layoutInflater : LayoutInflater = LayoutInflater.from(context)
//Connect TabLayout with ViewPager2
// TabLayoutMediator(tabLayout, viewPager){ tab, position ->
// tab.customView = prepareTabView(layoutInflater, tabLayout, adapter.getFragmentTabName(position), tabIcons[position])
// }.attach()
return root
}
// private fun prepareTabView(
// layoutInflater: LayoutInflater,
// tabLayout: TabLayout,
// fragmentName: String,
// drawableId: Int
// ): View {
//
// val rootView : View = layoutInflater.inflate(R.layout.main_custom_tab_text, tabLayout, false)
//
// val tabName : AppCompatTextView = rootView.findViewById(R.id.tabName)
//
// tabName.text = fragmentName
// tabName.setCompoundDrawablesWithIntrinsicBounds(null, AppCompatResources.getDrawable(requireContext(), drawableId), null, null)
//
// return tabName
//
// }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onResume() {
super.onResume()
requireView().isFocusableInTouchMode = true
requireView().requestFocus()
requireView().setOnKeyListener(object : View.OnKeyListener {
override fun onKey(v: View?, keyCode: Int, event: KeyEvent?): Boolean {
if (event!!.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
onBackPress()
return true
}
return false
}
})
}
fun onBackPress() {
if (viewPager.currentItem != 0)
viewPager.setCurrentItem(0, true)
else
requireActivity().onBackPressed()
}
}
这是父片段托管的ViewPager中显示的子片段之一
class AssetFragment : Fragment() {
companion object {
fun newInstance() = AssetFragment()
}
private lateinit var viewModel: AssetViewModel
private var _binding: FragmentAssetsBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private lateinit var logTxt: AppCompatTextView
private lateinit var recyclerView: RecyclerView
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentAssetsBinding.inflate(inflater, container, false)
val root: View = binding.root
recyclerView = binding.recyclerView
swipeRefreshLayout = binding.refreshLayout
logTxt = binding.errorLog
recyclerView.layoutManager = LinearLayoutManager(context)
adapter = AssetAdapter(requireContext(), this)
recyclerView.adapter = adapter
swipeRefreshLayout.isRefreshing = true
fetchAssets("30")
swipeRefreshLayout.setOnRefreshListener {
swipeRefreshLayout.isRefreshing = true
fetchAssets("30")
}
return root
}
private fun fetchAssets(limit: String) {
//Network stuff
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(this).get(AssetViewModel::class.java)
// TODO: Use the ViewModel
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
导航xml
这是将在抽屉菜单中显示的片段
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/nav_home">
<fragment
android:id="@+id/nav_home"
android:name="com.myapp.ui.home.HomeFragment"
android:label="@string/home"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/nav_marketcap"
android:name="com.myapp.ui.marketcap.MarketCapFragment"
android:label="@string/marketCap"
tools:layout="@layout/fragment_marketcap" />
<fragment
android:id="@+id/nav_about"
android:name="com.myapp.ui.about.AboutFragment"
android:label="@string/about"
tools:layout="@layout/fragment_about" />
</navigation>
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item android:title="@string/menu">
<menu>
<item
android:id="@+id/nav_home"
android:icon="@drawable/ic_assets"
android:title="@string/home" />
<item
android:id="@+id/nav_marketcap"
android:icon="@drawable/ic_marketcap"
android:title="@string/marketCap" />
<item
android:id="@+id/nav_about"
android:icon="@drawable/ic_about"
android:title="@string/about" />
</menu>
</item>
</group>
<item android:title="@string/connect">
<menu>
<item
android:id="@+id/email_connect"
android:icon="@drawable/ic_email"
android:title="@string/fui_email_hint" />
</menu>
</item>
</menu>
流量:
打开应用程序
启动MainActivity
显示HomeFragment(AssetFragment)
打开抽屉菜单
选择项目,例如About(AboutFragment)
按/向后滑动
这里的问题是HomeFragment onCreateView再次被触发
预期的行为家庭片段将不再需要膨胀视图,因为我们只是让用户回到第一个目的地。除非用户自己在我们的抽屉菜单中按下Home
项,否则将重新创建家庭片段。
根据《使用片段保存状态指南》,当片段位于后堆栈上时,预期会销毁并重新创建片段的视图(而不是片段本身)。
根据该指南,状态类型之一是非配置状态:
NonConfig:从外部源(例如服务器或本地存储库)提取的数据,或提交后发送到服务器的用户创建的数据。
NonConfig数据应该放在片段之外,例如在ViewModel中。ViewModel类本质上允许数据在配置更改(例如屏幕旋转)中生存,并在片段放在后堆栈时保留在内存中。
因此,您的片段不应该在onCreateView()
中调用fetchAsset("30")
。相反,此逻辑应该发生在ViewModel中,以便当片段从后堆栈返回时,它立即可用。根据ViewModel指南,您的fetchAsset
应该在ViewModel中完成,并且您的片段将观察该数据。
所以我用FragmentStatePagerAdapter实现了一个ViewPager,我有两个片段。我用参数1和2调用了setOffscreenPageLimit(),希望片段不会被重新创建,但是第一个片段总是被重新创建,而第二个片段被创建。 第一个片段总是经过这些步骤,只要它离开视野(向右滑动到另一个片段,或者点击主页按钮,等等...) on暂停 onStop onAttach 创建 onCr
问题内容: 在我的.xhtml页面中,我具有以下形式: CustomerTemplate.xhtml是: 这是我的ManagedBean: 如您所见,我的MrBean是ViewScoped ManagedBean。我希望@PostContruct函数只会在页面第1次呈现时被调用一次。但是,当我单击该按钮时,即使我仍在同一视图上,我也遇到了该行中的null异常。 如果有人能给我有关如何解决此问题的建
因此,我有一个DatePicker ChildComponent,我需要从父级通过访问它的。基本上一切正常。 但有一个问题。 每次我更新与DatePickerChildComponents没有任何关系的父其他儿童组件时,DatePicker仍然在渲染,即使它不应该渲染。 我试图删除从父级到子级的ref传递,然后每当我更新我想要解决的其他组件时,组件不再重新提交。 我已经开始使用回调备忘录,通过使用
configure脚本创建一个名为'config.status'的文件,用它描述在包最后一次进行配置时 给出的配置选项。该文件是一个shell脚本文件,如果运行它,将重新创建相同的配置。 你可以用'--recheck'选项调用'config.status'以更新它自身。如果你修改了configure, 该选项是有用的,这是因为某些测试的结果可能会与上一次运行的结果不同。选项'--recheck'以
http://prntscr.com/9jhrwa“GUI看起来怎么样” 公共类Okno1扩展javax.swing.jFrame{ 在这里,我显示了按下这个按钮时的jScrollPanel,我还显示了如果我想在显示的JList中获得选定元素的索引时必须按下的按钮 在这里,我按下一个按钮,它应该为我提供所选项的索引,但它一直给我-1,无论JList上的项是否被选中都无关紧要
问题内容: 我最近在SSRS-2008标记中回答了这个问题,要求将日期中的天数更改为序数(即“ 1st”,“ 2nd”而不是“ 1”,“2”)。该解决方案涉及VB.Net功能。我很好奇如何在SQL中执行此任务(特别是t-sql和SQL Server),或者是否有内置的支持。 因此,这是一个场景:假设您为1000个跑步者组织了一场比赛,并将结果存储在带有“名称”和“位置”(以正常数字表示)列的表格中