当前位置: 首页 > news >正文

四海网络网站建设咨询/百度大数据查询

四海网络网站建设咨询,百度大数据查询,视觉设计与制作,个人养老保险网上怎么缴费一、背景 在Android应用中,除了正常的业务开发,我们也要关注性能问题。卡顿、内存溢出、内存泄漏等问题,直接的表现会反馈到用户体验上,用户体验不好导致应用被卸载或者换到其他平台。 在性能优化,各大公司都会付出一些…

一、背景

        在Android应用中,除了正常的业务开发,我们也要关注性能问题。卡顿、内存溢出、内存泄漏等问题,直接的表现会反馈到用户体验上,用户体验不好导致应用被卸载或者换到其他平台。

        在性能优化,各大公司都会付出一些代价,或者安排专人负责。有些新手也想做,但是无从下手,对专业工具和专业代码使用以及分析比较吃力,排查起来也比较费劲。如果有专业的工具能够只管的把这些记录并标记好。这样新手也可以通过详情的问题去排查,那么LeaksCanary就是这款工具了。

二、性能的简单介绍(在面试的时候,也经常会被问起)

1、卡顿:卡顿的主要涉及到线程的使用,在LeaksCanary中,会给出当前线程的使用信息

2、内存溢出:是程序在申请内存时,没有足够的内存空间供其使用

3、内存泄漏:是程序在申请内存后,无法释放已申请的内存空间

三、LeaksCanary

1、介绍

        LeakCanary是Square公司为Android开发者提供的一个自动检测内存泄漏的工具,

LeakCanary本质上是一个基于MAT进行Android应用程序内存泄漏自动化检测的的开源工具,我们可以通过集成LeakCanary提供的jar包到自己的工程中,一旦检测到内存泄漏,LeakCanary就会dump Memory信息,并通过另一个进程分析内存泄漏的信息并展示出来,随时发现和定位内存泄漏问题,而不用每次在开发流程中都抽出专人来进行内存泄漏问题检测,极大地方便了Android应用程序的开发。

2、github地址:

GitHub - square/leakcanary: A memory leak detection library for Android.https://www.baidu.com/link?url=bcGyW7ySy9cW2azMXz5h-je6EtkwbMggSIlaEiFfWbtIqf3Yx3rak5qcn3Om3WJp&wd=&eqid=87caa544001114160000000463e1f198

 3、接入

3.1依赖库:

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:2.9.1'

3.2、代码引入

2.9.1的库已kotlin开发语言为核心,网络上大多数还是1.6.1。这就导致在接入的时候无法方式不同。

1.6.1版本,直接在application中,通过LeakCanary.install(application),来完成。

2.9.1接入:

在androidManifest中引入

<providerandroid:name="leakcanary.internal.MainProcessAppWatcherInstaller"android:authorities="${applicationId}.leakcanary-installer"android:enabled="@bool/leak_canary_watcher_auto_install"android:exported="false" />

leak_canary_watcher_auto_install:

<resources><bool name="leak_canary_watcher_auto_install">true</bool>
</resources>

是否自动安装,如果你不想自动安装,可以自行社会一个变量引入,默认不自动安装

介绍:MainProcessAppWatcherInstaller

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

MainProcessAppWatcherInstaller安装是ContentProvider的一个派生类。安装也是通过

AppWatcher.manualInstall(application)

安装方法manualInstall会做安装前的检查

如果不想通过自动安装,可以通过

Java:AppWatcher.INSTANCE.manualInstall(application);

kotlin:AppWatcher.manualInstall(application);

如果不想自己控制,可以在xml资源文件,设置为true。

注意:

        如果手动安装,最好判断一下是否已安装AppWatcher.isInstalled()否则会报错

四、卡顿问题优化:

        LeakCanary 造成卡顿的原因就是在主进程中 dump hprof 文件,文件就会涉及到IO操作,在读写时,占用大量线程,导致页面会出现卡顿情况。针对这个问题,可以通过引入多进程方案。避免在IO时,影响主进程

leakcanary-android-process

依赖库:

debugImplementation 'com.squareup.leakcanary:leakcanary-android-process:2.9.1'

        该库的核心是RemoteLeakCanaryWorkerService,这个服务就是多进程的核心。我们使用的时候,需要提前注册这个service。

在该service中:

  override fun onCreate() {// Ideally we wouldn't need to install AppWatcher at all here, however// the installation triggers InternalsLeakCanary to store the application instance// which is then used by the event listeners that respond to analysis progress.if (!AppWatcher.isInstalled) {val application = super.getApplicationContext() as ApplicationAppWatcher.manualInstall(application,// Nothing to watch in the :leakcanary process.watchersToInstall = emptyList())}super.onCreate()}

 在oncreate中,执行安装。

其实,在核心库中,已加入了该service。我们只需要通过

HeapDump:核心

RemoteWorkManagerHeapAnalyzer

        WorkManger也是一款开源工具,用于后台工作的架构组件,需要兼顾机会和有保证的执行。机会性执行意味着WorkManager将尽快完成您的后台工作。

依赖库:

def versions_work = "2.3.3"
implementation "androidx.work:work-runtime:$versions_work"

五、线上接入:

        目前很多调试都是在debug下进行,通过专业工具去处理。但是我们一旦打包以后会移除debug这些模块。如果线上发生了这些,如何获取?

        很多开发人员通过获取句柄文件来分析,但是如果我们没有问题设备,就无法获取到dump的句柄文件。这时,如果能把句柄文件传回到日志服务器,这样就方便开发人员定位信息。

  线上使用 LeakCanary,首要要确定以下问题:

  1. 如何获取 LeakCanary 分析的结果?
  2. 结果以何种形式上报到质量平台上?
  3. 如何确定合理的监控采集时机,尽可能小的影响用户体验?

定义自己的监听:

        上面我们介绍了workmanager这个工具,他就是通过定义一个监听,来完成后台的处理,减少主进程的线程操作,降低卡顿。同样我们也可以定义自己的EventListener。

目前LeakCanary的方法中已提供了一些监听:

   val eventListeners: List<EventListener> = listOf(LogcatEventListener,ToastEventListener,LazyForwardingEventListener {if (InternalLeakCanary.formFactor == TV) TvEventListener else NotificationEventListener},when {RemoteWorkManagerHeapAnalyzer.remoteLeakCanaryServiceInClasspath ->RemoteWorkManagerHeapAnalyzerWorkManagerHeapAnalyzer.validWorkManagerInClasspath -> WorkManagerHeapAnalyzerelse -> BackgroundThreadHeapAnalyzer}),

小试牛刀:

import leakcanary.EventListenerclass MyLeakCanaryEventListener:EventListener {override fun onEvent(event: EventListener.Event) {}}


Event:

目前已提供了如下Event

1、class DumpingHeap(uniqueId: String) : Event(uniqueId)

从“LeakCanary堆转储”HandlerThread发送

2、class HeapDump( uniqueId: String, val file: File, val durationMillis: Long, val reason: String) : Event(uniqueId)

从“LeakCanary堆转储”HandlerThread发送

3、class HeapDumpFailed( uniqueId: String, val exception: Throwable, val willRetryLater: Boolean) : Event(uniqueId)

从“LeakCanary堆转储”HandlerThread发送。失败

4、class HeapAnalysisProgress( uniqueId: String, val step: Step, val progressPercent: Double) : Event(uniqueId)

从执行分析的线程发送。

5、sealed class HeapAnalysisDone<T : HeapAnalysis>(  uniqueId: String,  val heapAnalysis: T,  showIntent: Intent) : Event(uniqueId)

5.1、class HeapAnalysisSucceeded( uniqueId: String, heapAnalysis: HeapAnalysisSuccess, val unreadLeakSignatures: Set<String>, showIntent: Intent)

分析成功,

5.2、class HeapAnalysisFailed( uniqueId: String, heapAnalysis: HeapAnalysisFailure, showIntent: Intent)

分析失败

这些类都是继承了class Event( val uniqueId: String),且都是内部类。

 分析结果:

        if (event is EventListener.Event.HeapAnalysisDone.HeapAnalysisSucceeded) {//分析成功val successEvent = event as EventListener.Event.HeapAnalysisDone.HeapAnalysisSucceededval list = successEvent.heapAnalysis.allLeakslist?.let {for (leak in it) {leak.leakTraces}}}

这样我们就可以得到了分析结果。

六、注册监听:

注册监听涉及到LeakCanary的配置,这边我们先讲解一下LeakCanary.Config配置参数

 data class Config(/*** Whether LeakCanary should dump the heap when enough retained instances are found. This needs* to be true for LeakCanary to work, but sometimes you may want to temporarily disable* LeakCanary (e.g. for a product demo).** Defaults to true.*/val dumpHeap: Boolean = true,/*** If [dumpHeapWhenDebugging] is false then LeakCanary will not dump the heap* when the debugger is attached. The debugger can create temporary memory leaks (for instance* if a thread is blocked on a breakpoint).** Defaults to false.*/val dumpHeapWhenDebugging: Boolean = false,/*** When the app is visible, LeakCanary will wait for at least* [retainedVisibleThreshold] retained instances before dumping the heap. Dumping the heap* freezes the UI and can be frustrating for developers who are trying to work. This is* especially frustrating as the Android Framework has a number of leaks that cannot easily* be fixed.** When the app becomes invisible, LeakCanary dumps the heap after* [AppWatcher.retainedDelayMillis] ms.** The app is considered visible if it has at least one activity in started state.** A higher threshold means LeakCanary will dump the heap less often, therefore it won't be* bothering developers as much but it could miss some leaks.** Defaults to 5.*/val retainedVisibleThreshold: Int = 5,/*** Known patterns of references in the heap, added here either to ignore them* ([IgnoredReferenceMatcher]) or to mark them as library leaks ([LibraryLeakReferenceMatcher]).** When adding your own custom [LibraryLeakReferenceMatcher] instances, you'll most* likely want to set [LibraryLeakReferenceMatcher.patternApplies] with a filter that checks* for the Android OS version and manufacturer. The build information can be obtained by calling* [shark.AndroidBuildMirror.fromHeapGraph].** Defaults to [AndroidReferenceMatchers.appDefaults]*/val referenceMatchers: List<ReferenceMatcher> = AndroidReferenceMatchers.appDefaults,/*** List of [ObjectInspector] that provide LeakCanary with insights about objects found in the* heap. You can create your own [ObjectInspector] implementations, and also add* a [shark.AppSingletonInspector] instance created with the list of internal singletons.** Defaults to [AndroidObjectInspectors.appDefaults]*/val objectInspectors: List<ObjectInspector> = AndroidObjectInspectors.appDefaults,/*** Deprecated, add to LeakCanary.config.eventListeners instead.* Called on a background thread when the heap analysis is complete.* If you want leaks to be added to the activity that lists leaks, make sure to delegate* calls to a [DefaultOnHeapAnalyzedListener].** Defaults to [DefaultOnHeapAnalyzedListener]*/@Deprecated(message = "Add to LeakCanary.config.eventListeners instead")val onHeapAnalyzedListener: OnHeapAnalyzedListener = DefaultOnHeapAnalyzedListener.create(),/*** Extracts metadata from a hprof to be reported in [HeapAnalysisSuccess.metadata].* Called on a background thread during heap analysis.** Defaults to [AndroidMetadataExtractor]*/val metadataExtractor: MetadataExtractor = AndroidMetadataExtractor,/*** Whether to compute the retained heap size, which is the total number of bytes in memory that* would be reclaimed if the detected leaks didn't happen. This includes native memory* associated to Java objects (e.g. Android bitmaps).** Computing the retained heap size can slow down the analysis because it requires navigating* from GC roots through the entire object graph, whereas [shark.HeapAnalyzer] would otherwise* stop as soon as all leaking instances are found.** Defaults to true.*/val computeRetainedHeapSize: Boolean = true,/*** How many heap dumps are kept on the Android device for this app package. When this threshold* is reached LeakCanary deletes the older heap dumps. As several heap dumps may be enqueued* you should avoid going down to 1 or 2.** Defaults to 7.*/val maxStoredHeapDumps: Int = 7,/*** LeakCanary always attempts to store heap dumps on the external storage if the* WRITE_EXTERNAL_STORAGE is already granted, and otherwise uses the app storage.* If the WRITE_EXTERNAL_STORAGE permission is not granted and* [requestWriteExternalStoragePermission] is true, then LeakCanary will display a notification* to ask for that permission.** Defaults to false because that permission notification can be annoying.*/val requestWriteExternalStoragePermission: Boolean = false,/*** Finds the objects that are leaking, for which LeakCanary will compute leak traces.** Defaults to [KeyedWeakReferenceFinder] which finds all objects tracked by a* [KeyedWeakReference], ie all objects that were passed to* [ObjectWatcher.expectWeaklyReachable].** You could instead replace it with a [FilteringLeakingObjectFinder], which scans all objects* in the heap dump and delegates the decision to a list of* [FilteringLeakingObjectFinder.LeakingObjectFilter]. This can lead to finding more leaks* than the default and shorter leak traces. This also means that every analysis during a* given process life will bring up the same leaking objects over and over again, unlike* when using [KeyedWeakReferenceFinder] (because [KeyedWeakReference] instances are cleared* after each heap dump).** The list of filters can be built from [AndroidObjectInspectors]:** ```kotlin* LeakCanary.config = LeakCanary.config.copy(*     leakingObjectFinder = FilteringLeakingObjectFinder(*         AndroidObjectInspectors.appLeakingObjectFilters*     )* )* ```*/val leakingObjectFinder: LeakingObjectFinder = KeyedWeakReferenceFinder,/*** Dumps the Java heap. You may replace this with your own implementation if you wish to* change the core heap dumping implementation.*/val heapDumper: HeapDumper = AndroidDebugHeapDumper,/*** Listeners for LeakCanary events. See [EventListener.Event] for the list of events and* which thread they're sent from. You most likely want to keep this list and add to it, or* remove a few entries but not all entries. Each listener is independent and provides* additional behavior which you can disable by not excluding it:** ```kotlin* // No cute canary toast (very sad!)* LeakCanary.config = LeakCanary.config.run {*   copy(*     eventListeners = eventListeners.filter {*       it !is ToastEventListener*     }*   )* }* ```*/val eventListeners: List<EventListener> = listOf(LogcatEventListener,ToastEventListener,LazyForwardingEventListener {if (InternalLeakCanary.formFactor == TV) TvEventListener else NotificationEventListener},when {RemoteWorkManagerHeapAnalyzer.remoteLeakCanaryServiceInClasspath ->RemoteWorkManagerHeapAnalyzerWorkManagerHeapAnalyzer.validWorkManagerInClasspath -> WorkManagerHeapAnalyzerelse -> BackgroundThreadHeapAnalyzer}),/*** Deprecated: This is a no-op, set a custom [leakingObjectFinder] instead.*/@Deprecated("This is a no-op, set a custom leakingObjectFinder instead")val useExperimentalLeakFinders: Boolean = false)

默认都是有值,对应参数如下:

      private var dumpHeap = config.dumpHeapprivate var dumpHeapWhenDebugging = config.dumpHeapWhenDebuggingprivate var retainedVisibleThreshold = config.retainedVisibleThresholdprivate var referenceMatchers = config.referenceMatchersprivate var objectInspectors = config.objectInspectorsprivate var onHeapAnalyzedListener = config.onHeapAnalyzedListenerprivate var metadataExtractor = config.metadataExtractorprivate var computeRetainedHeapSize = config.computeRetainedHeapSizeprivate var maxStoredHeapDumps = config.maxStoredHeapDumpsprivate var requestWriteExternalStoragePermission =config.requestWriteExternalStoragePermissionprivate var leakingObjectFinder = config.leakingObjectFinderprivate var heapDumper = config.heapDumperprivate var eventListeners = config.eventListenersprivate var useExperimentalLeakFinders = config.useExperimentalLeakFinders

新增我们的监听:

       val eventListeners = LeakCanary.config.eventListeners.toMutableList().apply {add(MyLeakCanaryEventListener())}LeakCanary.config=LeakCanary.config.copy(eventListeners=eventListeners)

这样整个线上监听基本完成。

我们只要对LeakTrace进行分析,把结果存储后,在一个合适的时机上报给服务器即可

七、AppWatcher的看守配置:

        知道如何去分析这些问题,LeakCanary还提供了看门机制,监听哪些也是可以通过配置的。

在AppWatcher中,也提供了Config

  data class Config(@Deprecated("Call AppWatcher.manualInstall() with a custom watcher list")val watchActivities: Boolean = true,@Deprecated("Call AppWatcher.manualInstall() with a custom watcher list")val watchFragments: Boolean = true,@Deprecated("Call AppWatcher.manualInstall() with a custom watcher list")val watchFragmentViews: Boolean = true,@Deprecated("Call AppWatcher.manualInstall() with a custom watcher list")val watchViewModels: Boolean = true,@Deprecated("Call AppWatcher.manualInstall() with a custom retainedDelayMillis value")val watchDurationMillis: Long = TimeUnit.SECONDS.toMillis(5),@Deprecated("Call AppWatcher.appDefaultWatchers() with a custom ReachabilityWatcher")val enabled: Boolean = true) 

可以看守的有以下,默认都是开启,如果你想关闭哪个,默认设为false即可

AppWatcher.config= AppWatcher.config.copy(watchActivities = false, enabled = false)

这样,我们就可以很好的看守我们想要的结果。

八、总结:

        通过接入、卡顿优化、拦截、配置等,能够很好的满足我们从线上到线下的各种把控。可以很好的完善应用的监控与优化机制。

        Debug模式,直接在LeaksApp中可以很好的看到问题列表。其他更多的可以参考github的开源信息,或者自己接入调试。

http://www.jmfq.cn/news/4886821.html

相关文章:

  • 弹幕网站制作/无锡哪里有做网站的
  • iis网站ip/班级优化大师怎么下载
  • 交互界面设计/商丘seo博客
  • 做网站和百度推广有什么不一样/企业推广的渠道有哪些
  • 给网站做广告/网站关键词优化怎么弄
  • wordpress网站开发代码/重庆网站网络推广
  • 网站建设发票能抵扣增值税/2345电脑版网址导航
  • 郑州网站建设优化公司/企业网站管理系统源码
  • 做公司网站需要什么/宁波seo网络推广渠道介绍
  • 网站怎么做图片轮播/浙江网络推广
  • 企企业业网网站站建建设设/百度指数官方下载
  • 扁平风格企业网站源码/台州seo排名优化
  • 一个超链接 多个网站/指数型基金是什么意思
  • 做网站推广的好处/百度推广账户登陆
  • 做一个中英文网站的价格/宁波免费建站seo排名
  • 佛山企业网站建设公司/百度网页版登录首页
  • 做社交网站有哪些/长春网站优化流程
  • 闵行手机网站建设/提高网站排名软件
  • wordpress插件 破解/嘉兴seo外包
  • php动态网站模板/福建seo搜索引擎优化
  • 什么网站做简历模板/小红书推广引流软件
  • 盐城seo网站优化/网络营销的应用
  • 企业网站的建立必要性/百度在线人工客服
  • 商务网站制作工程师/长沙seo培训班
  • 在html中做网站 视频/百度浏览器app下载
  • 做资讯网站需要什么条件/域名备案
  • 信誉好的邯郸网站建设/搜索引擎推广一般包括哪些
  • 注册了网站怎么建设/浏览器里面信息是真是假
  • 微信网页开发教程/搜索引擎优化人员优化
  • 做网站推广都有哪些行业/seo研究中心怎么样