Android 性能调优以及相关面试

一、谈谈对Android性能优化方面的了解?

  • 启动优化:application中不要做大量耗时操作,如果必须的话,建议异步做耗时操作。
  • 布局优化:使用合理的控件选择,少做嵌套。(合理使用include,merge,viewStub)
  • apk优化:资源文件优化,代码优化,lint检查,.9png,合理使用shape代替图片布局,
  • 性能优化,网络优化,电量优化:
  1. 避免轮询,尽量使用推送
  2. 应用处于 后台时,禁用某些数据传输
  3. 限制访问频率,失败后不要无限重连
  4. 选用合适的定位服务
  5. 使用缓存
  6. startActivityForResult替代发送广播
  •    内存优化
  1. 循环尽量不要使用局部变量
  2.  避免在onDraw中创建对象,onDraw会被频繁调用,容易造成内存抖动,循环中创建大的对象,也是如此。
  3. 不用的对象要及时回收和释放
  4. 数据库游标cursor要及时关闭
  5. adaper使用缓存
  6. 注册广播后,在生命周期结束时要反注册
  7. 及时关闭流操作
  8. 图片尽量使用软引用,较大的图片可以通过图片压缩后在使用,并及时recycle
  9. 避免static成员变量引用资源耗费过多实例
  10. 避免静态内部类的引用

二、谈谈布局优化的技巧?

  1. 降低Overdraw(过度绘制),减少不必要的背景绘制
  2. 减少嵌套层级以及控件个数
  3. 使用Canvas的clipPath方法限制view的绘制区域
  4. 通过imageDrawable方法进行设置避免imageView的background和imageDrawable重叠
  5. 借助viewStub按需延迟加载
  6. 选择合适的布局类型
  7. 熟悉API尽量借助系统现有的属性来实现UI的效果

三、谈谈Android中内存优化的方式?

        关于内存泄漏,一般像单例模式的使用不当啊、集合的操作不当啊、资源的缺乏有效的回收机制啊、Handler、线程的使用不当等等都有可能引发内存泄漏。

  1. 单例模式引发的内存泄漏:
    原因:单例模式里的静态实例持有对象的引用,导致对象无法被回收,常见为持有Activity的引用
    优化:改为持有Application的引用,或者不持有使用的时候传递。
  2. 集合操作不当引发的内存泄漏:
    原因:集合只增不减
    优化:有对应的删除或卸载操作
  3. 线程的操作不当引发的内存泄漏:
    原因:线程持有对象的引用在后台执行,与对象的生命周期不一致
    优化:静态实例+弱引用(WeakReference)方式,使其生命周期一致
  4. 匿名内部类/非静态内部类操作不当引发的内存泄漏:
    原因:内部类持有对象引用,导致无法释放,比如各种回调
    优化:保持生命周期一致,改为静态实例+对象的弱引用方式(WeakReference)
  5. 常用的资源未关闭回收引发的内存泄漏:
    原因:BroadcastReceiver,File,Cursor,IO流,Bitmap等资源使用未关闭
    优化:使用后有对应的关闭和卸载机制
  6. Handler使用不当造成的内存泄漏:
    原因:Handler持有Activity的引用,其发送的Message中持有Handler的引用,当队列处理Message的时间过长会导致Handler无法被回收
    优化:静态实例+弱引用(WeakReference)方式
    内存溢出:
    原因:
    1.内存泄漏长时间的积累
    2.业务操作使用超大内存
    优化:
    1.调整图像大小后再放入内存、及时回收
    2.不要过多的创建静态变量

 四、ANR 出现的场景以及解决方案?

        场景:

  1. 触摸无响应5s
  2. BroadCastReciver前台处理时间超过10s,后台处理时间超过60s
  3. Server 前台处理超过20s,后台处理超过200s

        ANR出现的类型有两种

  1.  主线程耗时导致的
  2. CPU、内存、IO占用过高资源消耗

        如何避免

  1.  不要在主线程中做耗时的操作
  2. 避免CPU占用过高、简化方法,减少执行时间
  3. 避免内存占用过高,防止内存泄漏

五、哪些情况下会导致oom问题? 

        1、根据java的内存模型会出现内存溢出的内存有堆内存、方法区内存、虚拟机栈内存、native方法区内存;
        2、一般说的OOM基本都是针对堆内存;
        3、对于堆内存溢出主的根本原因有两种
(1)app进程内存达到上限
(2)手机可用内存不足,这种情况并不是我们app消耗了很多内存,而是整个手机内存不足
        4、而我们需要解决的主要是app的内存达到上限
        5、对于app内存达到上限只有两种情况
(1)申请内存的速度超出gc释放内存的速度
(2)内存出现泄漏,gc无法回收泄漏的内存,导致可用内存越来越少
        6、对于申请内存速度超出gc释放内存的速度主要有2种情况
(1)往内存中加载超大文件
(2)循环创建大量对象
        7、一般申请内存的速度超出gc释放内存基本不会出现,内存泄漏才是出现问题的关键所在
        8、内存泄漏常见场景
(1)资源对象没关闭造成的内存泄漏(如: Cursor、File等)
(2)全局集合类强引用没清理造成的内存泄漏(特别是 static 修饰的集合)
(3)接收器、监听器注册没取消造成的内存泄漏,如广播,eventsbus
(4)Activity 的 Context 造成的泄漏,可以使用 ApplicationContext
(5)单例中的static成员间接或直接持有了activity的引用
(6)非静态内部类持有父类的引用,如非静态handler持有activity的引用
        9、怎么对内存进行优化呢
三个方向
(1)为应用申请更大内存,把manifest上的largdgeheap设置为true
(2)减少内存的使用
        ①使用优化后的集合对象,比如SpaseArray;
        ②使用微信的mmkv替代sharedpreference;
        ③对于经常打log的地方使用StringBuilder来组拼,替代String拼接
        ④统一带有缓存的基础库,特别是图片库,如果用了两套不一样的图片加载库就会出现2个图片各自维护一套图片缓存
        ⑤给ImageView设置合适尺寸的图片,列表页显示缩略图,查看大图显示原图
        ⑥优化业务架构设计,比如省市区数据分批加载,需要加载省就加载省,需要加载市就加载失去,避免一下子加载所有数据
(3)避免内存泄漏
编码规范上:
        ①资源对象用完一定要关闭,最好加finally
        ②静态集合对象用完要清理
        ③接收器、监听器使用时候注册和取消成对出现
        ④context使用注意生命周期,如果是静态类引用直接用ApplicationContext
        ⑤使用静态内部类
        ⑥结合业务场景,设置软引用,弱引用,确保对象可以在合适的时机回收
建设内存监控体系:
线下监控:
        ①使用ArtHook检测图片尺寸是否超出imageview自身宽高的2倍
        ②编码阶段Memery Profile看app的内存使用情况,是否存在内存抖动,内存泄漏,结合Mat分析内存泄漏
线上监控:
        ①上报app使用期间待机内存、重点模块内存、OOM率
        ②上报整体及重点模块的GC次数,GC时间
        ③使用LeakCannery自动化内存泄漏分析
        10、真的出现低内存,设置一个兜底策略
低内存状态回调,根据不同的内存等级做一些事情,比如在最严重的等级清空所有的bitmap,关掉所有界面,直接强制把app跳转到主界面,相当于app重新启动了一次一样,这样就避免了系统Kill应用进程,与其让系统kill进程还不如浪费一些用户体验,自己主动回收内存

六、自定义 Handler 时如何有效地避免内存泄漏问题?

        1.自定义的静态handler
        2.可以加一个弱引用
        3.还有一个主意的就是当你activity被销毁的时候如果还有消息没有发出去 就remove掉吧
        4.removecallbacksandmessages去清除Message和Runnable 加null 写在生命周的ondestroy()就行

七、一般什么情况下会导致内存泄漏问题?

  1. 资源对象没关闭造成的内存泄漏(如: CursorFile等)
  2. Bitmap 对象不在使用时调用recycle()释放内存
  3. 集合中对象没清理造成的内存泄漏(特别是 static 修饰的集合)
  4. 接收器、监听器注册没取消造成的内存泄漏
  5. Activity 的 Context 造成的泄漏,可以使用 ApplicationContext
  6. Handler 造成的内存泄漏问题(一般由于 Handler 生命周期比其外部类的生命周期长引起的)

八、 Android 中怎样做图片优化方案?

       1、我们可以对图片进行二次采样,从本质上减少图片的内存占用。就是将大图片缩小之后放入到内存中,以实现减小内存的目的
        2、其次就是采用三层缓存架构,提高图片的访问速度。三层缓存架构是内存-文件-网络。

    内存是访问速度最快的部分但是分配的空间有限,所以不可能占用太多。其中内存缓存可以采用LRU算法(最近最少使用算法),来确定要删除内存中的那些图片,保存那   些图片。

    文件就是将图片保存到本地,可以使SD卡中,也可以是手机内部存储中。

    网络就是访问网络下载图片,进行图片的加载。
        3、常见的png,JPG,webp等格式的图片在设置到UI上之前需要经过解码过程,而图片采用不同的码率,也会造成对内存的占用不同。
        4、重用Bitmap,不使用bitmap要记得实时回收,减小内存的开销

九、谈谈你是如何优化App启动过程的?

        1、把application oncreate 中要执行的方法 分为同步和异步,尽量去延迟执行 或者使用空闲线程
去初始化一些方法
        2、配置一个启动背景,避免白屏或者黑屏,然后做一个空的Activity这个Activity只做一件事,就是跳转到真的Activity,因为 启动速度 和application oncreate的耗时和第一个Activity的绘制有关,
上面都是easy的做法

        3、利用 redex 工具 优化 dex , 因为 class字节码 分布在不同的dex中,所以启动的时候必须逐个查找一些文件,他们散列分布在不同的dex中,查找起来耗时又不方便,利用redex 把相关的class 放在同一个dex包下,避免 同一个dex包被多次查找

        4、在attachedbaseContext中 新起一个进程 去加载 mutildex 可以加速App启动页的打开(可能在启动页中会等待,但是加速了从launcher到启动页的速度)

十、谈谈App的电量优化?

  • 避免轮循。可以利用推送。如果非要轮循,合理的设置频率。
  • 应用处于后台时,避免某些数据的传输,比如感应器,定位,视频缓存。
  • 页面销毁时,取消掉网络请求。
  • 限制访问频率,失败后不要无限的重连。
  • 合理的选择定位精度和频率。
  • 使用缓存。如果数据变化周期比较长,可以出一个配置接口,用于记录那些接口有变化。没变化的直接用缓存。
  • 减少广播的使用频率。可以用观察者,startActivityForResult等代替。

十一、谈谈如何对WebView进行优化?

  1. 单/多线程:webView在独立进程中,那么webview的进程奔溃不会影响到主进程运行,同时WebView的安全漏洞也很难影响到主进程;如果是多进程的话,可以使用webView的容器池,有二次秒开的作用,不过缺点就是需要你做好喝WebView的跨进程通讯
  2. 网络优化:我们可以让webView的host和客户端的host保持一致,那么就达到复用DNS缓存的效果,如果客户端有针对网络请求进行优化,那么可以让WebView的全部网络请求托管给客户端
  3. H5离线包,这个是H5的方案之一,让客户端提前下载离线的H5数据包,WebView只需要加载本地的H5数据包即可,这么做不仅可以避免一些HTTP的劫持,而且跳过了WebView的建立TCP连接和H5,CSS等数据下载过程,直接开始UI渲染,大大提高WebView的效率。

十二、如何处理大图的加载? 

         1、首先确定大图的用途,精度需求:
                a)完整显示,对精度要求不高,图片本身就很大
                b)对精度需求比较高,不需要完整显示
        2、解决方案
                a)针对第一种的处理图片本身,按需加载根据显示设备本身大小进行缩放,降低精度加载(改变图片模式,如将ARGB8888改成RGB565,ARGB4444),修改图片格式(png改成webp,jpg)
                b)第二种的一般采用局部加载,主要要用到的是BitmapRegionDecoder这个类decodeRegion的方法,读取图片指定大小的数据,然后通过移动来动态改变显示区域的图片

十三、谈谈如何对网络请求进行优化?

        1.最开始的是DNS,当我们发起一个网络请求,首先要经过DNS服务,将域名转化为IP地址,为避免DNS解析异常问题,可以直接使用 IP 建立连接;
        2.使用 Gzip 压缩 Response 减少数据传输量;使用 Protocol Buffer 代替 JSON;
        3.请求图片的 url 中可以添加 格式、质量、宽高等参数;使用缩略图、使用 WebP格式图片,大图分片传输;
        4.使用网络缓存,使用图片加载框架;
        5.监听设备网络状态,根据不同网络状态选择对应情况下的网络请求策略:网络良好和弱网、离线等情况下分别设计不同的请求策略,比如 WIFI 下一个请求可以获取几十个数据,甚至可以一次性执行多个请求;而弱网下一个请求获取几个数据,且文本类型优先,富文本其次,除文本数据外其它类型的数据一开始只显示占位符;离线下事先保存请求数据到磁盘,在离线时从磁盘加载数据。 

十四、 请谈谈如何加载Bitmap并防止内存溢出?

  • 根据不同的密度的设备将图片资源放置再不同的drawable文件夹中;
  • 利用inSampleSize对图片进行尺寸上的压缩;
  • 利用inPreferredConfig对图片进行质量上的压缩;
  • 利用三级缓存,依次从内存缓存(LruCache)磁盘缓存(DiskLruCache)网络上获取图片;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值