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,去掉最后一个属性即可

 这样的话,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()
            }
        }
    }
}

欢迎评论批评指正

你可能感兴趣的:(android,android-studio,kotlin)