[dev_arch_opt_3.0][leakfix]生命周期对象销毁时,直接将匿名内部类引用的字段置null
This commit is contained in:
@@ -7,10 +7,14 @@ import android.view.View
|
|||||||
import androidx.annotation.*
|
import androidx.annotation.*
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.fragment.app.*
|
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.*
|
||||||
import com.knightboost.lancet.api.annotations.*
|
import com.knightboost.lancet.api.annotations.*
|
||||||
import com.knightboost.lancet.api.annotations.Weaver
|
import com.knightboost.lancet.api.annotations.Weaver
|
||||||
import com.mogo.eagle.core.utilcode.kotlin.*
|
import com.mogo.eagle.core.utilcode.kotlin.*
|
||||||
|
import io.netty.util.internal.ConcurrentSet
|
||||||
import java.lang.ref.*
|
import java.lang.ref.*
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@@ -35,6 +39,7 @@ internal class AccessSyntheticUtils {
|
|||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val fields = ConcurrentHashMap<String, WeakReference<Any>>()
|
private val fields = ConcurrentHashMap<String, WeakReference<Any>>()
|
||||||
|
private val observers = ConcurrentSet<String>()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isTargetAlive(obj: Any): Boolean {
|
fun isTargetAlive(obj: Any): Boolean {
|
||||||
@@ -64,31 +69,72 @@ internal class AccessSyntheticUtils {
|
|||||||
fields.remove(key)
|
fields.remove(key)
|
||||||
}
|
}
|
||||||
}?.get()?.let { t ->
|
}?.get()?.let { t ->
|
||||||
when(t) {
|
var lifecycle: Lifecycle? = null
|
||||||
|
val ret = when (t) {
|
||||||
is View -> {
|
is View -> {
|
||||||
|
lifecycle = t.lifecycleOwner.lifecycle
|
||||||
ViewCompat.isAttachedToWindow(t)
|
ViewCompat.isAttachedToWindow(t)
|
||||||
}
|
}
|
||||||
is Activity -> {
|
is Activity -> {
|
||||||
|
lifecycle = t.findViewById<View>(android.R.id.content)?.lifecycleOwner?.lifecycle
|
||||||
!t.isFinishing && !t.isDestroyed
|
!t.isFinishing && !t.isDestroyed
|
||||||
}
|
}
|
||||||
is Fragment -> {
|
is Fragment -> {
|
||||||
|
lifecycle = t.lifecycle
|
||||||
!t.isDetached
|
!t.isDetached
|
||||||
}
|
}
|
||||||
is android.app.Fragment -> {
|
is android.app.Fragment -> {
|
||||||
|
lifecycle = t.view?.lifecycleOwner?.lifecycle
|
||||||
!t.isDetached
|
!t.isDetached
|
||||||
}
|
}
|
||||||
is Dialog -> {
|
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 -> {
|
else -> {
|
||||||
true
|
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
|
} ?: true
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
t.printStackTrace()
|
t.printStackTrace()
|
||||||
}
|
}
|
||||||
return true
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user