You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中Fragment切换时保持RecyclerView加载状态的问题

Hey there! Let's break down how to fix your RecyclerView lag and high CPU usage when switching back to the Home Fragment.

First, Let's Understand the Root Cause

The default "Bottom navigation activity" template uses NavController with replace transactions when switching fragments. This means every time you leave the Home Fragment, it gets destroyed—so when you come back, onViewCreated runs again, reinitializing Firebase references, rebuilding the RecyclerView, and reloading data from scratch. That's why you're seeing slow load times and high CPU usage.

Solution 1: Keep Fragments Alive with Hide/Show Instead of Replace

Instead of letting the navigation system destroy your fragments, we'll manually manage fragment visibility (hide/show) so the Home Fragment stays in memory. Here's how to adjust your Main Activity:

class MainActivity : AppCompatActivity() {
    private lateinit var bottomNav: BottomNavigationView
    private val homeFragment = HomeFragment()
    private val otherFragment1 = OtherFragment1() // Replace with your actual fragments
    private val otherFragment2 = OtherFragment2()
    private var currentFragment: Fragment? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        bottomNav = findViewById(R.id.bottom_nav_view)

        // Set Home as the initial fragment
        currentFragment = homeFragment
        supportFragmentManager.beginTransaction()
            .add(R.id.nav_host_fragment, homeFragment)
            .commit()

        // Handle bottom nav clicks manually
        bottomNav.setOnItemSelectedListener { item ->
            when (item.itemId) {
                R.id.home -> switchFragment(homeFragment)
                R.id.your_second_item -> switchFragment(otherFragment1)
                R.id.your_third_item -> switchFragment(otherFragment2)
            }
            true
        }
    }

    private fun switchFragment(targetFragment: Fragment) {
        if (currentFragment == targetFragment) return

        supportFragmentManager.beginTransaction().apply {
            currentFragment?.let { hide(it) }
            if (!targetFragment.isAdded) {
                add(R.id.nav_host_fragment, targetFragment)
            } else {
                show(targetFragment)
            }
            commit()
        }
        currentFragment = targetFragment
    }
}

This way, your Home Fragment is never destroyed—just hidden when you switch away. When you come back, it’s instantly shown without reinitializing everything.

Solution 2: Optimize Your HomeFragment Code

Even with the fragment kept alive, your current code has inefficiencies that contribute to lag. Let's fix those:

class HomeFragment : Fragment() {
    private lateinit var mAuth: FirebaseAuth
    private lateinit var mDatabase: DatabaseReference
    private lateinit var mStorage: FirebaseStorage
    private lateinit var productAdapter: ProductsAdapter
    private var isViewSetup = false // Track if we've initialized the view once

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Initialize Firebase references ONCE, not every time the view is created
        mAuth = FirebaseAuth.getInstance()
        mDatabase = FirebaseDatabase.getInstance().reference
        mStorage = FirebaseStorage.getInstance()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_home, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        if (!isViewSetup) {
            // Configure RecyclerView ONLY once
            val productList = MainActivity.productList
            val gridLayoutManager = GridLayoutManager(context, 3, LinearLayoutManager.VERTICAL, false)
            val topSpacingItemDecoration = TopSpacingItemDecoration(20)
            
            fh_productView.apply {
                addItemDecoration(topSpacingItemDecoration)
                layoutManager = gridLayoutManager
                setHasFixedSize(true)
                productAdapter = ProductsAdapter(productList, "HomeFragment")
                adapter = productAdapter
            }

            // Setup add product button once
            fh_addProduct.setOnClickListener {
                startActivity(Intent(context, AddProductActivity::class.java))
            }

            isViewSetup = true
        } else {
            // If we're coming back, just refresh the adapter data (if needed)
            productAdapter.updateData(MainActivity.productList)
        }
    }
}

Then add an update method to your ProductsAdapter to refresh data without rebuilding the adapter:

class ProductsAdapter(
    private var productList: MutableList<Product>,
    private val fragmentTag: String
) : RecyclerView.Adapter<ProductsAdapter.ViewHolder>() {

    // ... your existing adapter code ...

    fun updateData(newList: List<Product>) {
        productList.clear()
        productList.addAll(newList)
        notifyDataSetChanged()
        // For better performance, use DiffUtil instead of notifyDataSetChanged() here
    }
}

Key fixes here:

  • Moved Firebase initialization to onCreate (runs once per fragment instance)
  • Only configure the RecyclerView once, using a flag to avoid redundant work
  • Replaced the companion object adapter with a member variable (prevents memory leaks)
  • Added a way to refresh adapter data instead of recreating the adapter entirely

Final Notes

  • Avoid storing views/adapters in companion objects—they can cause memory leaks by holding references to destroyed fragments.
  • If you need to refresh data after adding a product (returning from AddProductActivity), you can use onResume or a ViewModel to observe data changes instead of relying on MainActivity.productList.

内容的提问来源于stack exchange,提问作者Simon Bergmark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:07:29