欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android LeakCanary的使用方法介紹

 更新時間:2022年09月07日 15:15:10   作者:且聽真言  
在Android的性能優(yōu)化中,內(nèi)存優(yōu)化是必不可少的點,而內(nèi)存優(yōu)化最重要的一點就是解決內(nèi)存泄漏的問題,在Android的內(nèi)存泄漏分析工具也不少,比如PC端的有:AndroidStudio自帶的Android Profiler、MAT等工具;手機端也有,就是我們今天要介紹的LeakCanary

1.LeakCanary 如何自動初始化

LeakCanary只需添加依賴就可以實現(xiàn)自動初始化。LeakCanary是通過ContentProvider實現(xiàn)初始化的,在ContentProvider 的 onCreate方法中初始化LeakCanary。并且MainProcessAppWatcherInstaller是在主線程中初始化的。注意:ContentProvider的初始化是在Application的onCreate之前完成的,所以LeakCanary的初始化方法AppWatcher.manualInstall(application)也是在Application的onCreate之前完成的。

internal class MainProcessAppWatcherInstaller : ContentProvider() {
   override fun onCreate(): Boolean {
      val application = context!!.applicationContext as Application
      AppWatcher.manualInstall(application)
      return true
    }
     ... ...
}

2.LeakCanary如何檢測內(nèi)存泄漏

2.1LeakCanary初始化時做了什么

AppWatcher.kt

@JvmOverloads
fun manualInstall(
  application: Application,
  retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
  watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
) {
  checkMainThread()
  if (isInstalled) {
    throw IllegalStateException(
      "AppWatcher already installed, see exception cause for prior install call", installCause
    )
  }
  check(retainedDelayMillis >= 0) {
    "retainedDelayMillis $retainedDelayMillis must be at least 0 ms"
  }
  installCause = RuntimeException("manualInstall() first called here")
  this.retainedDelayMillis = retainedDelayMillis
  if (application.isDebuggableBuild) {
    LogcatSharkLog.install()
  }
  // Requires AppWatcher.objectWatcher to be set
  LeakCanaryDelegate.loadLeakCanary(application)
  watchersToInstall.forEach {
    it.install()
  }
}
fun appDefaultWatchers(
  application: Application,
  reachabilityWatcher: ReachabilityWatcher = objectWatcher
): List<InstallableWatcher> {
  return listOf(
    ActivityWatcher(application, reachabilityWatcher),
    FragmentAndViewModelWatcher(application, reachabilityWatcher),
    RootViewWatcher(reachabilityWatcher),
    ServiceWatcher(reachabilityWatcher)
  )
}

在appDefaultWatchers方法中,會默認初始化一些Watcher,在默認情況下,我們只會監(jiān)控Activity,Fragment,RootView,Service這些對象是否泄漏。

2.2LeakCanary如何觸發(fā)檢測

以ActivityWatcher為例:

/**
 * Expects activities to become weakly reachable soon after they receive the [Activity.onDestroy]
 * callback.
 */
class ActivityWatcher(
  private val application: Application,
  private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {
  private val lifecycleCallbacks =
    object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
      override fun onActivityDestroyed(activity: Activity) {
        reachabilityWatcher.expectWeaklyReachable(
          activity, "${activity::class.java.name} received Activity#onDestroy() callback"
        )
      }
    }
  override fun install() {
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
  }
  override fun uninstall() {
    application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
  }
}

在Activity.onDestory時,就會觸發(fā)檢測內(nèi)存泄漏。通過ActivityLifecycleCallbacks監(jiān)聽生命周期變化,在onActivityDestroyed方法中調(diào)用ReachabilityWatcher的expectWeaklyReachable方法。

2.3LeakCanary如何檢測泄漏的對象

以Activity為例,通過ReachabilityWatcher的expectWeaklyReachable方法檢測。

fun interface ReachabilityWatcher {
  /**
   * Expects the provided [watchedObject] to become weakly reachable soon. If not,
   * [watchedObject] will be considered retained.
   */
  fun expectWeaklyReachable(
    watchedObject: Any,
    description: String
  )
}

ObjectWatcher.kt

ObjectWatcher實現(xiàn)ReachabilityWatcher接口。

private val watchedObjects = mutableMapOf()

private val queue = ReferenceQueue()

@Synchronized override fun expectWeaklyReachable(
  watchedObject: Any,
  description: String
) {
  if (!isEnabled()) {
    return
  }
  removeWeaklyReachableObjects()
  val key = UUID.randomUUID()
    .toString()
  val watchUptimeMillis = clock.uptimeMillis()
  val reference =
    KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue)
  SharkLog.d {
    "Watching " +
      (if (watchedObject is Class<*>) watchedObject.toString() else "instance of ${watchedObject.javaClass.name}") +
      (if (description.isNotEmpty()) " ($description)" else "") +
      " with key $key"
  }
  watchedObjects[key] = reference
  checkRetainedExecutor.execute {
    moveToRetained(key)
  }
}

1.通過觀察的實例watchedObject構(gòu)建弱引用KeyedWeakReference實例,watchedObject與ReferenceQueue關(guān)聯(lián),當對象被回收時,該弱引用對象將被存入ReferenceQueue當中。

2.弱引用KeyedWeakReference實例會被被存儲在watchedObjects中(Map)。

3.檢測過程中,會調(diào)用removeWeaklyReachableObjects,將已回收對象從watchedObjects中移除。

4.如果watchedObjects中沒有移除對象,證明它沒有被回收,那么就會調(diào)用moveToRetained。

private fun removeWeaklyReachableObjects() {
  // WeakReferences are enqueued as soon as the object to which they point to becomes weakly
  // reachable. This is before finalization or garbage collection has actually happened.
  var ref: KeyedWeakReference?
  do {
    ref = queue.poll() as KeyedWeakReference?
    if (ref != null) {
      watchedObjects.remove(ref.key)
    }
  } while (ref != null)
}
@Synchronized private fun moveToRetained(key: String) {
  removeWeaklyReachableObjects()
  val retainedRef = watchedObjects[key]
  if (retainedRef != null) {
    retainedRef.retainedUptimeMillis = clock.uptimeMillis()
    onObjectRetainedListeners.forEach { it.onObjectRetained() }
  }
}

2.4弱引用 WeakReference

只要 GC 發(fā)現(xiàn)一個對象只有弱引用,則就會回收此弱引用對象。

public class WeakReference<T> extends Reference<T> {
    public WeakReference(T referent) {
        super(referent);
    }
    public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }
}
var str: Any? = Any()
val quque = ReferenceQueue<Any>()
val weakReference = WeakReference<Any>(str, quque)
val weakReference_before_gc = weakReference.get()
Log.v("reference_tag", weakReference_before_gc.toString())
str = null
System.gc()
Handler().postDelayed( {
    val weakReference_after_gc = weakReference.get()
    Log.v("reference_tag", weakReference_after_gc.toString())
}, 2000)

2022-02-27 17:43:04.181 16634-16634/com.example.myapplication V/reference_tag: java.lang.Object@c87946a
2022-02-27 17:43:06.182 16634-16634/com.example.myapplication V/reference_tag: null

到此這篇關(guān)于Android LeakCanary的使用方法介紹的文章就介紹到這了,更多相關(guān)Android LeakCanary內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android開發(fā)Jetpack組件Room使用講解

    Android開發(fā)Jetpack組件Room使用講解

    Room是一個數(shù)據(jù)庫訪問組件; 對SqLite數(shù)據(jù)庫做了友好的封裝,使我們在編碼的時候,只需要注重邏輯的部分即可,數(shù)據(jù)庫就交給Room去流暢的訪問即可
    2022-08-08
  • Android 常見bug匯總及解決方案

    Android 常見bug匯總及解決方案

    這篇文章主要介紹了Android 常見bug匯總及解決方案,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下
    2021-03-03
  • Android ContentProvider基礎(chǔ)應用詳解

    Android ContentProvider基礎(chǔ)應用詳解

    ContentProvider是android四大組件之一。它是不同應用程序之間交換數(shù)據(jù)的標準api,ContentProvider以某種uri的形式對外提供數(shù)據(jù),允許其它應用程序?qū)ζ湓L問或者修改數(shù)據(jù)。本文將介紹ContentProvider的基礎(chǔ)應用,感興趣的可以學習一下
    2021-12-12
  • Android消息機制Handler用法總結(jié)

    Android消息機制Handler用法總結(jié)

    這篇文章介紹了Android消息機制Handler用法總結(jié),對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-11-11
  • Android Handler內(nèi)存泄漏詳解及其解決方案

    Android Handler內(nèi)存泄漏詳解及其解決方案

    在android開發(fā)過程中,我們可能會遇到過令人奔潰的OOM異常,這篇文章主要介紹了Android Handler內(nèi)存泄漏詳解及其解決方案,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Android程序開發(fā)通過HttpURLConnection上傳文件到服務器

    Android程序開發(fā)通過HttpURLConnection上傳文件到服務器

    這篇文章主要介紹了Android程序開發(fā)通過HttpURLConnection上傳文件到服務器的相關(guān)資料,需要的朋友可以參考下
    2016-01-01
  • Android模擬器中窗口截圖存成文件實現(xiàn)思路及代碼

    Android模擬器中窗口截圖存成文件實現(xiàn)思路及代碼

    Android模擬器內(nèi)容是用OpenGL渲染的,所以用一般的編程截圖(如PrintWindow()等)會是黑屏。這是因為畫的東西放在framebuffer里 接下來介紹如何實現(xiàn)Android模擬器中窗口截圖存成文件,感興趣的朋友可以了解下哦
    2013-01-01
  • Android實現(xiàn)漂亮的Gallery畫廊

    Android實現(xiàn)漂亮的Gallery畫廊

    這篇文章主要為大家詳細介紹了Android實現(xiàn)漂亮的Gallery畫廊,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • Android仿微信頁面底部導航效果代碼實現(xiàn)

    Android仿微信頁面底部導航效果代碼實現(xiàn)

    本文給大家分享一段代碼有關(guān)android仿微信頁面底部導航效果代碼實現(xiàn)的思路,非常不錯,感興趣的朋友一起看看吧
    2016-09-09
  • Gradle 依賴切換源碼實踐示例詳解

    Gradle 依賴切換源碼實踐示例詳解

    這篇文章主要為大家介紹了Gradle 依賴切換源碼實踐示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12

最新評論