接上一篇,上一篇分析了Activity的检测,继续来看剩下的Fragment、ViewModel 、RootView、Service的检测
Fragment、ViewModel 泄漏检测
根据上一篇的内容,可以知道Fragment的泄漏检测是在FragmentAndViewModelWatcher中的install方法中注册
override fun install() {
//也是调用Application注册监听所有Activity中实现
application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
}
继续看lifecycleCallbacks中的处理
private val lifecycleCallbacks =
object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
//监听所有Activity的onCreate方法
override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?
) {
//调用添加的watcher方法
for (watcher in fragmentDestroyWatchers) {
watcher(activity)
}
}
}
继续看fragmentDestroyWatchers中怎么添加数据的
private val fragmentDestroyWatchers: List<(Activity) -> Unit> = run {
//最后返回的就是这个list,所以看list中添加什么样的数据
val fragmentDestroyWatchers = mutableListOf<(Activity) -> Unit>()
//如果sdk版本大于O,也就是26,这里先默认大于,走这个if
if (SDK_INT >= O) {
//往list中添加AndroidOFragmentDestroyWatcher对象
fragmentDestroyWatchers.add(
AndroidOFragmentDestroyWatcher(reachabilityWatcher)
)
}
//判断是否为androidx 包下面的fragment,
//如果是就通过反射创建一个AndroidXFragmentDestroyWatcher对象,并添加到list中
getWatcherIfAvailable(
ANDROIDX_FRAGMENT_CLASS_NAME,
ANDROIDX_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
reachabilityWatcher
)?.let {
fragmentDestroyWatchers.add(it)
}
//判断是否为v4 包下面的fragment,
//如果是就通过反射创建一个AndroidSupportFragmentDestroyWatcher对象,并添加到list中
getWatcherIfAvailable(
ANDROID_SUPPORT_FRAGMENT_CLASS_NAME,
ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
reachabilityWatcher
)?.let {
fragmentDestroyWatchers.add(it)
}
fragmentDestroyWatchers
}
先来看如果sdk大于26的情况下,AndroidOFragmentDestroyWatcher的处理。再添加到list中,在循环中调用watcher(activity)方法时,会走到对应的list中数据的invoke方法中,看AndroidOFragmentDestroyWatcher.invoke()方法
override fun invoke(activity: Activity) {
//获取fragmentManager
val fragmentManager = activity.fragmentManager
//通过fragmentManager注册fragment生命周期监听
fragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
}
通过fragmentManager注册fragment生命周期监听,看对应监听方法
private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {
//监听fragment的ViewDestroyed方法,就是fragment中View销毁时回调
override fun onFragmentViewDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
//获取view
val view = fragment.view
if (view != null) {
//如果view不为null,进入观察方法中
reachabilityWatcher.expectWeaklyReachable(
view, "${fragment::class.java.name} received Fragment#onDestroyView() callback " +
"(references to its views should be cleared to prevent leaks)"
)
}
}
//监听fragment的Destroyed方法
override fun onFragmentDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
//观察这个fragment是否回收
reachabilityWatcher.expectWeaklyReachable(
fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
)
}
}
通过onFragmentViewDestroyed和onFragmentDestroyed方法分别监听fragment中view和自身的回收情况来判断是否出现泄漏,其中expectWeaklyReachable方法在上一篇已经介绍。
继续往下看,如果使用的androidx包下的framgent,进入AndroidXFragmentDestroyWatcher中invoke方法
override fun invoke(activity: Activity) {
//判断当前activity是否为FragmentActivity
if (activity is FragmentActivity) {
//获取supportFragmentManager
val supportFragmentManager = activity.supportFragmentManager
//同样通过supportFragmentManager注册framgent监听
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
//ViewModel监听
ViewModelClearedWatcher.install(activity, reachabilityWatcher)
}
}
先来看framgent的监听,也是走到对应的监听方法中
private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentCreated(
fm: FragmentManager,
fragment: Fragment,
savedInstanceState: Bundle?
) {
//注册framgent中的ViewModel肩痛
ViewModelClearedWatcher.install(fragment, reachabilityWatcher)
}
//同上,监听fragment的view
override fun onFragmentViewDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
val view = fragment.view
if (view != null) {
reachabilityWatcher.expectWeaklyReachable(
view, "${fragment::class.java.name} received Fragment#onDestroyView() callback " +
"(references to its views should be cleared to prevent leaks)"
)
}
}
//监听framgent的回收
override fun onFragmentDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
reachabilityWatcher.expectWeaklyReachable(
fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
)
}
}
framgnet的监听和前面O的监听一样,主要就是增加了一个ViewModel的监听,接下来看ViewModel的监听,走到ViewModelClearedWatcher.install方法中
fun install(
storeOwner: ViewModelStoreOwner,
reachabilityWatcher: ReachabilityWatcher
) {
//通过provider创建一个ViewModelClearedWatcher的ViewModel对象
val provider = ViewModelProvider(storeOwner, object : Factory {
@Suppress("UNCHECKED_CAST")
override fun create(modelClass: Class): T =
ViewModelClearedWatcher(storeOwner, reachabilityWatcher) as T
})
provider.get(ViewModelClearedWatcher::class.java)
}
}
上面代码就是创建一个ViewModelClearedWatcher对象,并将它和activity或fragment关联起来,当ViewMode回收时,会调用onCleared方法,所以走到ViewModelClearedWatcher的onCleared方法中
private val viewModelMap: Map?
init {
//init 方法在初始化的时候就会调用,在这里获取缓存ViewModel的mMap对象
// We could call ViewModelStore#keys with a package spy in androidx.lifecycle instead,
// however that was added in 2.1.0 and we support AndroidX first stable release. viewmodel-2.0.0
// does not have ViewModelStore#keys. All versions currently have the mMap field.
viewModelMap = try {
val mMapField = ViewModelStore::class.java.getDeclaredField("mMap")
mMapField.isAccessible = true
@Suppress("UNCHECKED_CAST")
mMapField[storeOwner.viewModelStore] as Map
} catch (ignored: Exception) {
null
}
}
override fun onCleared() {
//循环mMap中的数据,判断ViewModel是否出现泄漏
viewModelMap?.values?.forEach { viewModel ->
reachabilityWatcher.expectWeaklyReachable(
viewModel, "${viewModel::class.java.name} received ViewModel#onCleared() callback"
)
}
}
RootView泄漏检测
走到RootView泄漏检测的类中,也就是RootViewWatcher的install方法
override fun install() {
//如果sdk版本小雨19,直接返回,不检测
if (Build.VERSION.SDK_INT < 19) {
return
}
//这一段代码是,通过反射获取mView,拦截mView.add()方法,每当调用add方法是,就会走自身的onRootViewAdded方法,并将这个view传过去
swapViewManagerGlobalMViews { mViews ->
object : ArrayList(mViews) {
override fun add(element: View): Boolean {
onRootViewAdded(element)
return super.add(element)
}
}
}
}
//反射获取WindowManagerGlobal中的mView
@SuppressLint("PrivateApi")
@Suppress("FunctionName")
private fun swapViewManagerGlobalMViews(swap: (ArrayList) -> ArrayList) {
try {
val windowManagerGlobalClass = Class.forName("android.view.WindowManagerGlobal")
val windowManagerGlobalInstance =
windowManagerGlobalClass.getDeclaredMethod("getInstance").invoke(null)
val mViewsField =
windowManagerGlobalClass.getDeclaredField("mViews").apply { isAccessible = true }
@Suppress("UNCHECKED_CAST")
val mViews = mViewsField[windowManagerGlobalInstance] as ArrayList
mViewsField[windowManagerGlobalInstance] = swap(mViews)
} catch (ignored: Throwable) {
SharkLog.d(ignored) { "Could not watch detached root views" }
}
}
根据上面代码,可以知道,每当创建一个view并添加到mView中时,就会调用onRootViewAdded方法
private fun onRootViewAdded(rootView: View) {
//注册view的状态监听
rootView.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
val watchDetachedView = Runnable {
//执行view的泄露检测
reachabilityWatcher.expectWeaklyReachable(
rootView, "${rootView::class.java.name} received View#onDetachedFromWindow() callback"
)
}
override fun onViewAttachedToWindow(v: View) {
//添加到Window时,移除run
mainHandler.removeCallbacks(watchDetachedView)
}
override fun onViewDetachedFromWindow(v: View) {
//当view在window中销毁时,执行run
mainHandler.post(watchDetachedView)
}
})
}
总结一下view的泄漏检测,通过反射的方式获取mView,hook add 方法,每次调用add方法时,执行onRootViewAdded方法,通过注册view的状态变化,来观察view的泄漏
Service泄漏检测
走到ServiceWatcher. install方法中
override fun install() {
//做一些检查
checkMainThread()
check(uninstallActivityThreadHandlerCallback == null) {
"ServiceWatcher already installed"
}
check(uninstallActivityManager == null) {
"ServiceWatcher already installed"
}
try {
//和前面hook mView差不多,不过是hook mH 的callback
swapActivityThreadHandlerCallback { mCallback ->
uninstallActivityThreadHandlerCallback = {
swapActivityThreadHandlerCallback {
mCallback
}
}
Handler.Callback { msg ->
//当调用了service 的onDestroy时
if (msg.what == STOP_SERVICE) {
val key = msg.obj as IBinder
activityThreadServices[key]?.let {
//将这个service通过弱引用的方式保存到servicesToBeDestroyed中
onServicePreDestroy(key, it)
}
}
mCallback?.handleMessage(msg) ?: false
}
}
//继续hook,这里hook的是ActivityManagerService
swapActivityManager { activityManagerInterface, activityManagerInstance ->
uninstallActivityManager = {
swapActivityManager { _, _ ->
activityManagerInstance
}
}
//动态代理的方式
Proxy.newProxyInstance(
activityManagerInterface.classLoader, arrayOf(activityManagerInterface)
) { _, method, args ->
//当调用serviceDoneExecuting方法时,观察这个service的泄漏情况
if (METHOD_SERVICE_DONE_EXECUTING == method.name) {
//通过token获取service
val token = args!![0] as IBinder
if (servicesToBeDestroyed.containsKey(token)) {
//观察service泄漏情况
onServiceDestroyed(token)
}
}
try {
if (args == null) {
method.invoke(activityManagerInstance)
} else {
method.invoke(activityManagerInstance, *args)
}
} catch (invocationException: InvocationTargetException) {
throw invocationException.targetException
}
}
}
} catch (ignored: Throwable) {
SharkLog.d(ignored) { "Could not watch destroyed services" }
}
}
最后走到onServiceDestroyed方法中
private fun onServiceDestroyed(token: IBinder) {
servicesToBeDestroyed.remove(token)?.also { serviceWeakReference ->
serviceWeakReference.get()?.let { service ->
//检测service的泄漏情况
reachabilityWatcher.expectWeaklyReachable(
service, "${service::class.java.name} received Service#onDestroy() callback"
)
}
}
}
总结一些service的泄漏检测,通过hook mH回调的service的onDestroy的方法,将该service保存到activityThreadServices。hook AMS,当调用了serviceDoneExecuting方法时,判断service是否出现泄漏。