Android解决fragment来回切换重新实例化问题
4. 关于androidstudio自生成的xml文件的代码修改
1. 关于Android studio新建的Bottom Navigation Activity
AndroidStudio自带的生成的Navigation控制fragment的转换是直接使用的replace()方法,这会使每次点击底部的按钮都会重新实例化一个fragment,无论是跳转到其它fragment还是点击当前fragment对应的按钮。
而要使fragment不被回收并重新实例化,需要使用hide()和show()方法,具体实现下文。
2. 解决思路
首先在MainActivity实例化fragment,将所有fragment包含在list中。方便使用FragmentTransaction来实现对fragment的操作
private val home = HomeFragment()
private val dash = DashboardFragment()
private val notification = NotificationsFragment()
val list = arrayListOf(home, dash, notification)
构建一个FragmentTransaction来实现操作,以及两个Int变量获取当前fragment和要跳转的目的fragment
private lateinit var transaction: FragmentTransaction
var mFragment = 0
var toFragment = 0
这样就能实现对fragment的精准操控,这些定义都是全局变量
3. 具体操作
1. 首先是第一次打开的初始化,显示homefragment,即打开的默认的fragment
private fun init(){
transaction = supportFragmentManager.beginTransaction()
transaction.add(R.id.nav_host_fragment_activity_main, home).show(home).commit()
}
R.id.nav_host_fragment_activity_main是activity_main中fragment控件的id,这是androidstudio生成时默认的。
2. 其次是转换fragment的实现函数通过两个简单的if语句实现不同的hide和show函数
private fun switchFragment(transaction: FragmentTransaction){
val from = list[mFragment]
val to = list[toFragment]
if (mFragment == toFragment) return
if (from.isAdded) {
if (to.isAdded) {
transaction.hide(from).show(to).commit()
} else {
transaction.add(R.id.nav_host_fragment_activity_main, to).hide(from).show(to).commit()
}
} else {
if (to.isAdded) {
transaction.add(R.id.nav_host_fragment_activity_main, from).hide(from).show(to).commit()
} else {
transaction.add(R.id.nav_host_fragment_activity_main, from)
.add(R.id.nav_host_fragment_activity_main, to).hide(from).show(to).commit()
}
}
}
具体逻辑自己理解
3. 最后是菜单按钮的点击事件
private fun click(){
binding.navView.setOnItemSelectedListener{
transaction = supportFragmentManager.beginTransaction()
when(it.itemId) {
R.id.navigation_home -> {
toFragment = 0
switchFragment(transaction)
mFragment = 0
}
R.id.navigation_dashboard -> {
toFragment = 1
switchFragment(transaction)
mFragment = 1
}
R.id.navigation_notifications -> {
toFragment = 2
switchFragment(transaction)
mFragment = 2
}
}
true
}
}
每次跳转前给toFragment赋值,跳转后给mFragment赋值,这样switch函数就能知道当前的fragment和目的fragment。
4. 关于androidstudio自生成的xml文件的代码修改
activity_main.xml文件中fragment标签,取消使用navigation绑定几个fragment,去掉最后一个属性即可
<fragment
android:id="@+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" 这一行删掉
/>
这样的话,res文件夹中的navigation文件夹就可以直接删除
贴一个MainActivity的全部代码吧
package com.example.testfragment
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentTransaction
import com.example.testfragment.databinding.ActivityMainBinding
import com.example.testfragment.ui.DashboardFragment
import com.example.testfragment.ui.HomeFragment
import com.example.testfragment.ui.NotificationsFragment
class MainActivity : AppCompatActivity() {
companion object{
private val home = HomeFragment()
private val dash = DashboardFragment()
private val notification = NotificationsFragment()
val list = arrayListOf(home, dash, notification)
private lateinit var transaction: FragmentTransaction
var mFragment = 0
var toFragment = 0
}
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
init()
click()
}
private fun init(){
transaction = supportFragmentManager.beginTransaction()
transaction.add(R.id.nav_host_fragment_activity_main, home).show(home).commit()
}
private fun click(){
binding.navView.setOnItemSelectedListener{
transaction = supportFragmentManager.beginTransaction()
when(it.itemId) {
R.id.navigation_home -> {
toFragment = 0
switchFragment(transaction)
mFragment = 0
}
R.id.navigation_dashboard -> {
toFragment = 1
switchFragment(transaction)
mFragment = 1
}
R.id.navigation_notifications -> {
toFragment = 2
switchFragment(transaction)
mFragment = 2
}
}
true
}
}
private fun switchFragment(transaction: FragmentTransaction){
val from = list[mFragment]
val to = list[toFragment]
if (mFragment == toFragment) return
if (from.isAdded) {
if (to.isAdded) {
transaction.hide(from).show(to).commit()
} else {
transaction.add(R.id.nav_host_fragment_activity_main, to).hide(from).show(to).commit()
}
} else {
if (to.isAdded) {
transaction.add(R.id.nav_host_fragment_activity_main, from).hide(from).show(to).commit()
} else {
transaction.add(R.id.nav_host_fragment_activity_main, from)
.add(R.id.nav_host_fragment_activity_main, to).hide(from).show(to).commit()
}
}
}
}
欢迎评论批评指正