How can I resolve this leak?
┬───
│ GC Root: Global variable in native code
│
├─ com.samsung.android.content.clipboard.SemClipboardManager$2 instance
│ Leaking: UNKNOWN
│ Retaining 204.4 kB in 4075 objects
│ Anonymous subclass of android.sec.clipboard.IClipboardDataPasteEvent$Stub
│ ↓ SemClipboardManager$2.this$0
│ ~~~~~~
├─ com.samsung.android.content.clipboard.SemClipboardManager instance
│ Leaking: UNKNOWN
│ Retaining 204.4 kB in 4074 objects
│ mContext instance of ....presentation.ui.login.LoginActivity with mDestroyed = true
│ ↓ SemClipboardManager.mContext
│ ~~~~~~~~
╰→ ....presentation.ui.login.LoginActivity instance
Leaking: YES (ObjectWatcher was watching this because ....presentation.ui.login.LoginActivity
received Activity#onDestroy() callback and Activity#mDestroyed is true)
Retaining 202.6 kB in 4027 objects
key = e0f29b52-1c73-4933-9856-a987582ccb1d
watchDurationMillis = 22643
retainedDurationMillis = 17638
mApplication instance of ....presentation.App
mBase instance of androidx.appcompat.view.ContextThemeWrapper
Here is my code:
@AndroidEntryPoint
class LoginActivity : AppCompatActivity(R.layout.activity_login) {
private val lessonsViewModel by viewModels<LoginViewModel>()
private var context: Context? = null
private var binding: ActivityLoginBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLoginBinding.inflate(layoutInflater)
setContentView(binding?.root)
context = this@LoginActivity
context?.let {
SemEmergencyManagerLeakingActivity.applyFix(context!!.applicationContext as Application)
}
with(binding!!) {
btnSignIn.setOnClickListener {
if (edtEMail.text.isNullOrBlank() || edtEMail.text.isNullOrEmpty()) {
txtInputUserName.error = getString(R.string.error_user_name)
if (!edtPasswords.text.isNullOrBlank() && !edtPasswords.text.isNullOrEmpty()) {
txtInputPassword.error = null
}
} else if (edtPasswords.text.isNullOrBlank() || edtPasswords.text.isNullOrEmpty()) {
txtInputPassword.error = getString(R.string.error_user_password)
if (!edtEMail.text.isNullOrBlank() && !edtEMail.text.isNullOrEmpty()) {
txtInputUserName.error = null
}
} else if (
!edtEMail.text.isNullOrBlank() &&
!edtEMail.text.isNullOrEmpty() &&
!edtPasswords.text.isNullOrBlank() &&
!edtPasswords.text.isNullOrEmpty()
) {
hideBtnSignIn()
callAPI(edtEMail.text.toString(), edtPasswords.text.toString())
}
}
}
}
private fun callAPI(userName: String, password: String) {
lifecycleScope.launch {
val response = lessonsViewModel.getLoginValues(userName, password)
response.observe(this@LoginActivity) {
when (it) {
is Resource.Success -> {
it.data?.let { vl ->
hideProgressBar()
disableBtnSignIn()
lessonsViewModel.saveTokensLogged(
TokensDataStore(
vl.token!!,
vl.privatetoken!!
)
)
val intent = Intent(context, MainActivity::class.java)
startActivity(intent)
finish()
}
}
is Resource.Error -> {
it.message?.let { msg ->
hideProgressBar()
showBtnSignIn()
when (msg) {
getString(R.string.invalid_login) -> {
Toast.makeText(
context,
R.string.error_user_pass,
Toast.LENGTH_LONG
)
.show()
}
getString(R.string.service_not_available) -> {
Toast.makeText(
context,
R.string.error_service_not_available,
Toast.LENGTH_LONG
)
.show()
}
else -> {
Toast.makeText(context, msg, Toast.LENGTH_LONG)
.show()
}
}
}
}
is Resource.Loading -> {
hideBtnSignIn()
showProgressBar()
}
}
}
}
}
private fun showBtnSignIn() {
binding!!.btnSignIn.visibility = View.VISIBLE
}
private fun hideBtnSignIn() {
binding!!.btnSignIn.visibility = View.INVISIBLE
}
private fun disableBtnSignIn() {
binding!!.btnSignIn.isEnabled = false
}
private fun hideProgressBar() {
binding!!.prLogin.visibility = View.INVISIBLE
}
private fun showProgressBar() {
binding!!.prLogin.visibility = View.VISIBLE
}
override fun onDestroy() {
context = null
binding = null
super.onDestroy()
}
}
Resolved it. I removed it:
override fun onDestroy() {
context = null
binding = null
super.onDestroy()
}
And change it to:
override fun onStop() {
super.onStop()
context = null
binding = null
finish()
}
And edit bellow:
val intent = Intent(context, MainActivity::class.java)
startActivity(intent)
finish()
To:
val intent = Intent(context, MainActivity::class.java)
startActivity(intent)