handler使用不当内存泄露。
静态变量持有Context 强引用 。
匿名内部类引起的内存泄露,最典型的例子就是Handler泄漏。
Stream io流,bitmap等使用后未关闭或者注销。
eventbus、广播等未关闭注册。
Android 中的 WebView 存在很大的兼容性问题,有些 WebView 甚至存在内存泄露的问题。所以通常根治这个问题的办法是为 WebView 开启另外一个进程,通过 AIDL 与主进程进行通信, WebView 所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。
作为一个内存检测泄露的工具框架。
LeakCanary实现内存泄漏的主要判断逻辑是这样的。当我们观察的Activity或者Fragment销毁时,我们会使用一个弱引用去包装当前销毁的Activity或者Fragment,并且将它与本地的一个ReferenceQueue队列关联。
在KeyedWeakReference内部,使用了key和name标识了一个被检测的WeakReference对象。在注释1处,将弱引用和引用队列 ReferenceQueue 关联起来,如果弱引用referent持有的对象被GC回收,JVM就会把这个弱引用加入到与之关联的引用队列referenceQueue中。即 KeyedWeakReference 持有的 Activity 对象如果被GC回收,该对象就会加入到引用队列 referenceQueue 中。
所以我们知道如果GC触发了,系统会将当前的引用对象存入队列中。
如果没有被回收,队列中则没有当前的引用对象。所以LeakCanary会去判断,ReferenceQueue是否有当前观察的Activity或者Fragment的引用对象,第一次判断如果不存在,就去手动触发一次GC,然后做第二次判断,如果还是不存在,则表明出现了内存泄漏。
核心的方法有三个: dispatchTouchEvent 、onInterceptTouchEvent 、 onTouchEvent
流程图如下:
在 Android 中,当用户在设备上触发一个操作时,比如点击屏幕或者按下物理键,这些操作将会产生一个事件,并且会被封装成一个 MotionEvent 或者 KeyEvent 对象。事件传递到 View 的过程如下:
如果事件最终被消费了,则该事件将不会继续传递到其它 View 进行处理,相反,如果事件未被消费,则它将传递给其它 View 进行处理。
当事件处理完成后,系统会将事件的处理结果返回给 Activity,具体流程如下:
问:Android中加载大图方案?
Android中加载大图有多种方案,以下是一些常用的方案:
更好的方案是在SubScaleSampleImageView中,将大图切片,再判断是否可见,如果可见则加入内存中,否则回收,减少了内存占用与抖动 同时根据不同的缩放比例选择合适的采样率,进一步减少内存占用 同时在子线程进行decodeRegion操作,解码成功后回调至主线程,减少UI卡顿.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; // 缩放比例,值越大,缩放比例越大,图片越小
Bitmap thumbnail = BitmapFactory.decodeFile(filePath, options);
imageView.setImageBitmap(thumbnail);
内存管理:Glide 对图片进行了内存管理,当加载超大图片时,它会将图片分成小块加载,而不是一次性将整个图片加载到内存中。这样可以避免内存溢出和应用程序崩溃的风险。
图片压缩:Glide 能够自动对图片进行压缩,减小图片的大小和分辨率,以降低对内存和性能的影响。这对于加载超大图片来说尤为重要,因为它们通常具有较高的像素密度和文件大小。
对于每一个 View:
如果是 ViewGroup 还会在 onMeasure 中,调用每个子 View 的 measure () 进行测量.
主题设置透明并设置启动图片防止白屏。
onCreate异步线程。少做初始化工作。idleHandler做不重要工作。gc抑制和核心线程绑定大核。
mainActivity和splashActivity合并。
核心功能核心页面内容优先显示。其他使用viewstub。
odex延后加载。
Glide源码相关和图片优化相关:
kotlin相关
kotlin优势:
语法糖,空安全,代码简洁,可对string类拓展自定义方法,协程解决了代码回调地狱问题。
协程相关问题:
本质上还是对线程的封装的一套api,Java是开辟线程,协程是通过调度线程去实现方法的挂起和恢复。所以可以开启非常多的协程而不会崩溃。
suspend是一个提醒作用。提醒你需要把方法异步,放在协程体里面。
协程工作的核心就是它内部的状态机,invokeSuspend() 函数。
所以函数即便被 suspend 修饰了,但是也未必会挂起。需要里面的代码编译后有返回值为 COROUTINE_SUSPENDED 这样的标记位才可以,所以程序执行到 case 0 的时候就 return 了。那就意味着方法被暂停了,那么协程也被暂停了。所以说协成的挂起实际上是方法的挂起,方法的挂起本质是 return。
图片在停止滑动后加载,
避免用大图片做背景。用shape做背景绘制。
使用TraceView 抓取日子后对总耗时排序,通过app的包名搜索关键字,定位到 耗时方法
google描述这2个函数对耗时是敏感的。
1 优化onBindViewHolder. 这个函数原来会根据从网络获取不同的状态,判断是否显示和隐藏背景,通过ImageView.setBackgroundResource()。
因为背景不是动态获取的,所以优化为默认在ImageView中显示,通过setVisibility显示和隐藏ImageView.
优化后再次抓取TraceView,滑动列表是会不断触发onBindViewHolder, 但耗时只有1ms左右。 显示应该避免setBackground这种耗时操作。
那如果你确实需要加载不同图片呢?可以使用Glide等图片加载框架,在快速滑动时显示默认图片,待停止滑动后,再加载显示图片图片。
3 固定高度,避免重复计算高度 RecyclerView.setHasFixedSize(true);
4,局部刷新列表item,或者使用工具类对比一下哪里需要刷新就刷新哪里。
海外上架相关经验:遵循上架政策,并兼容到30或者更高。
1.马甲包:混淆代码,加入垃圾代码(使用AndroidJunkCode插件生成)。
回:主要是客户端回调问题,点击下单-》查询一遍有没有掉单-》去自己后台下单-》拉起google支付-》支付成功--》客户端回调--》回调给自己后端--》发货--》调用消耗商品操作--》完成支付流程。
防止掉单:客户端轮询查订单信息,在启动或者登录后再查一遍是否有掉单情况(有没有订单未消费)。
在安卓应用中,可以通过以下方面来做性能优化:
在安卓开发中,有很多性能优化工具可供使用。以下是一些常见的性能优化工具:
这些工具可以帮助开发者定位应用程序的性能问题,并提供相应的解决方案。但需要注意的是,这些工具只是辅助性的,最终的性能优化还需要开发者进行具体的代码实现。
下面是一些 Android 中内存优化的细节:
在 Android 应用开发中,布局优化也是一项非常重要的工作,它直接关系到应用的运行效率和用户体验。以下是一些常见的布局优化细节:
1.android:exported 属性需要显式声明。以及应用休眠(隔几个月不启动将重置权限和禁止后台通知)。
2.PendingIntent指定flag :PendingIntent.FLAG_MUTABLE 或PendingIntent.FLAG_IMMUTABLE,否则报错。
3.位置权限申请变更:位置权限分为了大致位置和确切位置。申请权限需要适配。
4.前台服务启动限制:
除了一些特殊情况外,以 Android12 为目标平台的应用将无法在后台运行时启动前台服务。如果应用尝试在后台运行时启动前台服务,将会引发异常。针对此情况,Android12官网也给出了前台服务的推荐替代方案:WorkManager。
5.SplashScreen API,让App开发者可以自主设置启动应用的画面主题和外观
6.通知trampoline限制:,以Android12为目标平台的应用无法从用作通知 trampoline的服务或者广播中启动activity,也就是说应用构建的通知 setContentIntent()参数必须是 PendingIntent.getActivity。
安卓11适配:
强制分区存储:Android 11 需要使用 MediaStore API 访问访问共享存储空间中的媒体文件。除此以外还可以用
粗暴一点:获取外部存储管理权限。如果你的应用是手机管家、文件管理器这类需要访问大量文件的app,可以申请MANAGE_EXTERNAL_STORAGE权限,将用户引导至系统设置页面开启。
2.增加了单次授权。
3.请求位置权限调整
4.启动别的应用需要在清单文件添加
5.APK签名
Android 11 为目标平台的应用,仅通过v1 签名的应用无法在Android 11的设备上安装或更新。必须使用v2或更高版本进行签名。
同时Android 11 添加了对 APK 签名方案 v4 的支持。
其他安卓版本变化:
Android 6.0
应用权限管理
官方指纹支持
Doze电量管理
运行时权限机制->需要动态申请权限
Android 7.0
多窗口模式
支持Java 8语言平台
需要使用FileProvider访问照片
安装apk需要兼容
Android 8.0
通知
画中画
自动填充
后台限制
自适应桌面图标->适配
隐式广播限制
开启后台Service限制
Android 9.0
利用 Wi-Fi RTT 进行室内定位
刘海屏 API 支持
多摄像头支持和摄像头更新
不允许调用hide api
限制明文流量的网络请求 http
Android 10
暗黑模式
隐私增强(后台能否访问定位)
限制程序访问剪贴板
应用黑盒
权限细分需兼容
后台定位单独权限需兼容
设备唯一标示符需兼容
后台打开Activity 需兼容
非 SDK 接口限制 需兼容
ANR原因
从应用的角度上来讲,它的原因可以归结为以下几种:
应用在主线程上非常缓慢地执行涉及 I/O 的操作。
应用在主线程上进行长时间的计算。
主线程在对另一个进程进行同步 binder 调用,而后者需要很长时间才能返回。
主线程处于阻塞状态,等待子线程的长时间耗时操作完成。
主线程在进程中或通过 binder 调用与另一个线程之间发生死锁。主线程不只是在等待长操作执行完毕,而且处于死锁状态。
1、开发中检测ANR
StrictMode(严格模式)
开发中由于个人原因,多多少少都会可能写出造成ANR的代码,要想在开发中及时发现问题,可以使用StrictMode有助于您在开发应用时发现主线程上的意外 I/O 操作。
启用后台 ANR 对话框
只有在设备的开发者选项中启用了显示所有 ANR 时,Android 才会针对花费过长时间处理广播消息的应用显示 ANR 对话框。我们可以通过打开这个选项,在开发中及早发现相关问题。
TraceView
TraceView 是 Android SDK 中内置的一个工具,它可以加载 trace 文件,用图形的形式展示代码的执行时间、次数及调用栈,便于我们分析。(注意:Android Studio3.2之后已经弃用)
CPU Profiler
Android Studio3.2之后,CPU Profiler替代了TraceView,我们可以通过在通过记录应用交互过程获取相关方法执行顺序和耗时图,从而分析哪些方法耗时过长导致ANR。
1、修改主线程上耗时的代码
通过TraceView或者CPU Profiler可以找到应用中主线程忙碌时间超过5s的位置,然后把此处代码移到子线程操作。如一些网络操作、耗时计算等。
2、锁的竞争导致堵塞
如果主线程参与锁的竞争,有可能会导致主线程持续等待锁而造成堵塞的问题,从而引发ANR。所以最好还是避免主线程出现竞争锁的情况。
3、死锁
如果某资源被另一个线程所持有,而该线程又在等待主线程的资源,就会陷入死锁情况导致ANR。
4、广播接收器执行速度慢
如在广播接收器的onReceive()执行了长时间的耗时操作,就会可能导致ANR,所以应该把耗时操作放到子线程操作。
ANR检测方案有开源的BlockCanary 、ANR-WatchDog、SafeLooper,xCrash(爱奇艺), 还有根据谷歌原生系统接口监测的方案:FileObserver。
ANR-WatchDog 原理:如下图所示。
页面更新:2024-03-13
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号