Skip to content

Commit 4059282

Browse files
fix: MainFragment pager memory leaks (#453)
1 parent b6405a0 commit 4059282

File tree

3 files changed

+30
-30
lines changed

3 files changed

+30
-30
lines changed

app/src/main/java/org/openedx/app/MainFragment.kt

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ class MainFragment : Fragment(R.layout.fragment_main) {
3939
private val viewModel by viewModel<MainViewModel>()
4040
private val router by inject<DiscoveryRouter>()
4141

42-
private lateinit var adapter: NavigationFragmentAdapter
43-
4442
override fun onCreate(savedInstanceState: Bundle?) {
4543
super.onCreate(savedInstanceState)
4644
lifecycle.addObserver(viewModel)
@@ -89,26 +87,28 @@ class MainFragment : Fragment(R.layout.fragment_main) {
8987
requireArguments().remove(ARG_OPEN_TAB)
9088
}
9189

92-
private fun createTabList(openTabArg: String): List<Pair<Int, Fragment>> {
93-
val learnFragment = LearnFragment.newInstance(
94-
openTab = if (openTabArg == HomeTab.PROGRAMS.name) {
95-
LearnTab.PROGRAMS.name
96-
} else {
97-
LearnTab.COURSES.name
98-
}
99-
)
90+
private fun createTabList(openTabArg: String): List<Pair<Int, () -> Fragment>> {
91+
val learnFragmentFactory = {
92+
LearnFragment.newInstance(
93+
openTab = if (openTabArg == HomeTab.PROGRAMS.name) {
94+
LearnTab.PROGRAMS.name
95+
} else {
96+
LearnTab.COURSES.name
97+
}
98+
)
99+
}
100100

101-
return mutableListOf<Pair<Int, Fragment>>().apply {
102-
add(R.id.fragmentLearn to learnFragment)
103-
add(R.id.fragmentDiscover to viewModel.getDiscoveryFragment)
101+
return mutableListOf<Pair<Int, () -> Fragment>>().apply {
102+
add(R.id.fragmentLearn to learnFragmentFactory)
103+
add(R.id.fragmentDiscover to { viewModel.getDiscoveryFragment })
104104
if (viewModel.isDownloadsFragmentEnabled) {
105-
add(R.id.fragmentDownloads to DownloadsFragment())
105+
add(R.id.fragmentDownloads to { DownloadsFragment() })
106106
}
107-
add(R.id.fragmentProfile to ProfileFragment())
107+
add(R.id.fragmentProfile to { ProfileFragment() })
108108
}
109109
}
110110

111-
private fun addMenuItems(menu: Menu, tabList: List<Pair<Int, Fragment>>) {
111+
private fun addMenuItems(menu: Menu, tabList: List<Pair<Int, () -> Fragment>>) {
112112
val tabTitles = mapOf(
113113
R.id.fragmentLearn to resources.getString(R.string.app_navigation_learn),
114114
R.id.fragmentDiscover to resources.getString(R.string.app_navigation_discovery),
@@ -128,7 +128,7 @@ class MainFragment : Fragment(R.layout.fragment_main) {
128128
}
129129
}
130130

131-
private fun setupBottomNavListener(tabList: List<Pair<Int, Fragment>>) {
131+
private fun setupBottomNavListener(tabList: List<Pair<Int, () -> Fragment>>) {
132132
val menuIdToIndex = tabList.mapIndexed { index, pair -> pair.first to index }.toMap()
133133

134134
binding.bottomNavView.setOnItemSelectedListener { menuItem ->
@@ -173,21 +173,21 @@ class MainFragment : Fragment(R.layout.fragment_main) {
173173
} else {
174174
R.id.fragmentLearn
175175
}
176+
176177
HomeTab.PROFILE.name -> R.id.fragmentProfile
177178
else -> R.id.fragmentLearn
178179
}
179180
}
180181

181-
private fun initViewPager(tabList: List<Pair<Int, Fragment>>) {
182+
private fun initViewPager(tabList: List<Pair<Int, () -> Fragment>>) {
182183
binding.viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
183184
binding.viewPager.offscreenPageLimit = tabList.size
184-
185-
adapter = NavigationFragmentAdapter(this).apply {
186-
tabList.forEach { (_, fragment) ->
187-
addFragment(fragment)
185+
binding.viewPager.adapter = NavigationFragmentAdapter(this).apply {
186+
tabList.forEach { (_, fragmentFactory) ->
187+
// Use fragment factory to prevent memory leaks
188+
addFragment { fragmentFactory() }
188189
}
189190
}
190-
binding.viewPager.adapter = adapter
191191
binding.viewPager.isUserInputEnabled = false
192192
}
193193

core/src/main/java/org/openedx/core/adapter/NavigationFragmentAdapter.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
55

66
class NavigationFragmentAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
77

8-
private val fragments = ArrayList<Fragment>()
8+
private val fragmentFactories = ArrayList<() -> Fragment>()
99

10-
override fun getItemCount(): Int = fragments.size
10+
override fun getItemCount(): Int = fragmentFactories.size
1111

12-
override fun createFragment(position: Int): Fragment = fragments[position]
12+
override fun createFragment(position: Int): Fragment = fragmentFactories[position].invoke()
1313

14-
fun addFragment(fragment: Fragment) {
15-
fragments.add(fragment)
14+
fun addFragment(fragmentFactory: () -> Fragment) {
15+
fragmentFactories.add(fragmentFactory)
1616
}
1717
}

dashboard/src/main/java/org/openedx/learn/presentation/LearnFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ class LearnFragment : Fragment(R.layout.fragment_learn) {
9191
binding.viewPager.offscreenPageLimit = 2
9292

9393
adapter = NavigationFragmentAdapter(this).apply {
94-
addFragment(viewModel.getDashboardFragment)
95-
addFragment(viewModel.getProgramFragment)
94+
addFragment { viewModel.getDashboardFragment }
95+
addFragment { viewModel.getProgramFragment }
9696
}
9797
binding.viewPager.adapter = adapter
9898
binding.viewPager.setUserInputEnabled(false)

0 commit comments

Comments
 (0)