Android解决fragment来回切换重新实例化问题

1. 关于Android studio新建的Bottom Navigation Activity

2. 解决思路

3. 具体操作

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()
            }
        }
    }
}

欢迎评论批评指正

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-情绪零碎-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值