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 objectadapter 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
onResumeor a ViewModel to observe data changes instead of relying onMainActivity.productList.
内容的提问来源于stack exchange,提问作者Simon Bergmark

