Merge branch 'dev_arch_opt_3.0' into dev_robobus-m1-p-app-module_1.0.0_230112_1.0.0

This commit is contained in:
yangyakun
2023-02-06 18:50:17 +08:00
65 changed files with 1667 additions and 1872 deletions

View File

@@ -0,0 +1,140 @@
package com.mogo.launcher.lancet
import android.app.Activity
import android.app.Dialog
import android.content.Context
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
@Keep
@Weaver
@Group("memory_leak")
class MemoryLeakFix {
@Insert
@ImplementedInterface("java.lang.Runnable")
@TargetMethod(methodName = "run")
fun runProxy() {
if (AccessSyntheticUtils.isTargetAlive(This.get())) {
Origin.callVoid()
}
}
}
internal class AccessSyntheticUtils {
companion object {
private val fields = ConcurrentHashMap<String, WeakReference<Any>>()
private val observers = ConcurrentSet<String>()
@JvmStatic
fun isTargetAlive(obj: Any): Boolean {
try {
val clazz = obj.javaClass
if (!clazz.isAnonymousClass) {
return true
}
val key = clazz.name
return (fields[key] ?: clazz.declaredFields.find {
it.isSynthetic &&
((it.modifiers and Modifier.STATIC) == 0) &&
(View::class.java.isAssignableFrom(it.type) or
Context::class.java.isAssignableFrom(it.type) or
Fragment::class.java.isAssignableFrom(it.type) or
android.app.Fragment::class.java.isAssignableFrom(it.type) or
Dialog::class.java.isAssignableFrom(it.type)
)
}?.let {
it.isAccessible = true
val wf = WeakReference(it.get(obj), ReferenceQueue())
fields[key] = wf
wf
})?.also {
if (it.isEnqueued) {
//对像被垃圾回收了
fields.remove(key)
}
}?.get()?.let { 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 ->
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()
}
}
}
}