[dev_arch_opt_3.0][leakfix]生命周期对象销毁时,直接将匿名内部类引用的字段置null

This commit is contained in:
renwj
2023-02-06 12:03:38 +08:00
parent efe80d9ea8
commit 390aa3ef9e

View File

@@ -7,10 +7,14 @@ import android.view.View
import androidx.annotation.*
import androidx.core.view.ViewCompat
import androidx.fragment.app.*
import androidx.lifecycle.*
import androidx.lifecycle.Lifecycle.Event
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
import com.knightboost.lancet.api.*
import com.knightboost.lancet.api.annotations.*
import com.knightboost.lancet.api.annotations.Weaver
import com.mogo.eagle.core.utilcode.kotlin.*
import io.netty.util.internal.ConcurrentSet
import java.lang.ref.*
import java.lang.reflect.Modifier
import java.util.concurrent.ConcurrentHashMap
@@ -35,6 +39,7 @@ internal class AccessSyntheticUtils {
companion object {
private val fields = ConcurrentHashMap<String, WeakReference<Any>>()
private val observers = ConcurrentSet<String>()
@JvmStatic
fun isTargetAlive(obj: Any): Boolean {
@@ -64,31 +69,72 @@ internal class AccessSyntheticUtils {
fields.remove(key)
}
}?.get()?.let { t ->
when(t) {
var lifecycle: Lifecycle? = null
val ret = when (t) {
is View -> {
lifecycle = t.lifecycleOwner.lifecycle
ViewCompat.isAttachedToWindow(t)
}
is Activity -> {
lifecycle = t.findViewById<View>(android.R.id.content)?.lifecycleOwner?.lifecycle
!t.isFinishing && !t.isDestroyed
}
is Fragment -> {
lifecycle = t.lifecycle
!t.isDetached
}
is android.app.Fragment -> {
lifecycle = t.view?.lifecycleOwner?.lifecycle
!t.isDetached
}
is Dialog -> {
t.window?.decorView?.let { v -> ViewCompat.isAttachedToWindow(v) } ?: false
t.window?.decorView?.let {
v ->
lifecycle = v.lifecycleOwner.lifecycle
ViewCompat.isAttachedToWindow(v)
} ?: false
}
else -> {
true
}
}
if (!ret) {
assignFinalFieldNull(obj, t.javaClass)
} else {
val l = lifecycle
if (l != null && !observers.contains(key)) {
observers.add(key)
l.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Event) {
if (event == ON_DESTROY) {
assignFinalFieldNull(obj, t.javaClass)
observers.remove(key)
}
}
})
}
}
ret
} ?: true
} catch (t: Throwable) {
t.printStackTrace()
}
return true
}
@JvmStatic
private fun assignFinalFieldNull(obj: Any, fieldType: Class<*>) {
try {
obj.javaClass.declaredFields.find {
it.isSynthetic &&
((it.modifiers and Modifier.STATIC) == 0) && it.type == fieldType
}?.also {
it.isAccessible = true
it.set(obj, null)
}
} catch (t: Throwable) {
t.printStackTrace()
}
}
}
}