Skip to content

Instantly share code, notes, and snippets.

@mazzouzi
mazzouzi / pokemonDetailViewModel.kt
Created June 1, 2022 09:00
onCleared method to remove the reference to the repository
override fun onCleared() {
repository = null
super.onCleared()
}
@mazzouzi
mazzouzi / FunFact.kt
Last active June 1, 2022 09:01
Stack vs Heap memory management
fun main() {
val actor = Actor("Will", "Smith", 53) // (1)
val forName = actor.forName // (2)
val funFact = actor.getFunFact(forName) // (3)
println(funFact)
}
class Actor(val forName: String, val name: String, val age: Int) {
fun getFunFact(key: String?): String? = funFacts[key] // (3')
@mazzouzi
mazzouzi / build.gradle
Created June 14, 2022 08:50
Leak Canary dependancy
dependencies {
// debugImplementation because LeakCanary should only run in debug builds.
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
}
class DialogUtilLeak private constructor(private val context: Context?) {
fun showError(title: String?, message: String?) {
if (context == null || (context as Activity).isFinishing) {
return
}
MaterialAlertDialogBuilder(context)
.setCancelable(true)
.setTitle(title)
class BackgroundSolutionPresenter(val view: BackgroundLeakInterface) {
private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
// Log exception error to server
}
private val coroutineScope = CoroutineScope(Job() + exceptionHandler)
fun doSomeIntensiveWork() {
coroutineScope.launch {
delay(120000) // simulate intensive work
class BackgroundLeakPresenter(val view: BackgroundLeakInterface) {
private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
// Log exception error to server
}
private val coroutineScope = CoroutineScope(Job() + exceptionHandler)
fun doSomeIntensiveWork() {
coroutineScope.launch {
delay(120000) // simulate intensive work
object DialogUtilSolution {
fun showError(context: Context?, title: String?, message: String?) {
if (context == null || (context as? Activity?)?.isFinishing == true) {
return
}
MaterialAlertDialogBuilder(context)
.setCancelable(true)
.setTitle(title)
private fun onError(errorMessage: String) {
/**
* Here we pass a copy of the context as a parameter to every functions
* of DialogUtilSolution singleton.
* Once the function returns, the copy is popped off the stack
* -> no memory leak ✅
* Be careful, this code will still leak if the user changes configuration while
* the dialog is displayed because the dialog is not tied to the Activity's lifecycle upon
* recreation. Please check "solutionfinal" package for complete solution.
override fun onStop() {
super.onStop()
/**
* Always unregister to the Android API before the view gets destroyed
* -> no memory leak ✅
*/
activity?.unregisterReceiver(localBroadcastReceiver)
}
abstract class BaseTwoPanelsLeakFragment(
private val side: Fragment,
private val main: Fragment
) : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
childFragmentManager.beginTransaction().apply {
replace(R.id.side_container, side)
replace(R.id.main_container, main)