From 390aa3ef9ed19ee4824f1dc488d04ff2ae27583a Mon Sep 17 00:00:00 2001 From: renwj Date: Mon, 6 Feb 2023 12:03:38 +0800 Subject: [PATCH] =?UTF-8?q?[dev=5Farch=5Fopt=5F3.0][leakfix]=E7=94=9F?= =?UTF-8?q?=E5=91=BD=E5=91=A8=E6=9C=9F=E5=AF=B9=E8=B1=A1=E9=94=80=E6=AF=81?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E7=9B=B4=E6=8E=A5=E5=B0=86=E5=8C=BF=E5=90=8D?= =?UTF-8?q?=E5=86=85=E9=83=A8=E7=B1=BB=E5=BC=95=E7=94=A8=E7=9A=84=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=BD=AEnull?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/launcher/lancet/MemoryLeakFix.kt | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/mogo/launcher/lancet/MemoryLeakFix.kt b/app/src/main/java/com/mogo/launcher/lancet/MemoryLeakFix.kt index 4b9374ed5f..5357e485f6 100644 --- a/app/src/main/java/com/mogo/launcher/lancet/MemoryLeakFix.kt +++ b/app/src/main/java/com/mogo/launcher/lancet/MemoryLeakFix.kt @@ -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>() + private val observers = ConcurrentSet() @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(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() + } + } } } \ No newline at end of file