Android性能优化

    前言:还记得之前做一个app,服务器在新加坡,国内访问新加坡的网速很慢,再加上测试机又是东南亚的低端机,导致开发的时候经常遇到app卡死的情况,因而开始重视Android性能优化,个人觉得Android性能优化主要有以下几方面:网络优化、内存优化、布局优化、线程控制、精简app大小,下面就跟大家分享一下我在这些方面所做的一些优化

    1.网络优化:每次打开一个界面的时候我们可能会去请求服务器获取数据,这个时候如果网络状况很差的话,获取数据可能需要的时间比较长,而Android下的网络请求必须是在子线程执行,即每次进入界面请求数据的时候都会开子线程,如果在弱网情况下重复打开/关闭界面,那么可能就会导致某次请求到数据需要更新界面的时候,该界面已经销毁了,如果我们仍在在请求到数据后去更新界面的话很可能造成空指针异常(Activity已经finish),或者由于内部类持有外部Activity的实例导致Activity无法被回收,我们要做的就是在界面关闭的时候结束该界面的所有网络请求,但是在java里面是无法对一个线程立即停止的,那么做法就是让该线程尽快的执行完里面的操作
        ** 解决方案:1.我当时是自己封装的网络框架,该框架里面耗时的是获取到服务端返回的数据写流的一个过程,写流必然是在一个while循环里面执行,那么我们可以给while循环加个开关,在Activity.onDestroy的时候关闭写流,那么此次网络传输就会很快的执行完了,自然线程也就被释放了。如果用到了Handler,那么可在onDestroy里面调用清空Handler的removeCallbackAndMessages(null)移除所有的Message
                             2.大家都知道用第三方的图片加载框架,比如Glide,ImageLoader这些框架内部都是开辟了多个线程去下载图片的,那么在列表滑动的时候可以暂停图片加载,这样就不会导致弱网情况下加载下一页数据很慢或者界面卡顿的问题

    2.内存优化:为什么要内存优化,主要有以下几点
            2.1:内存占用过大:内存占用过大一般是Bitmap引起的,那么可以考虑将Bitmap缩小之后再展示,只加载可见部分的Bitmap(比如使用BitmapRegionDecoder),设置图片格式(比如ARGB_4444,RGB_565,ARGB_8888,ALPHA_8),使用后及时回收或者采用LRUCache,比如ImageLoader内部是三级缓存(采用LinkedHashMap实现LRU)
            2.2:内存抖动:内存抖动是指在短时间内有大量的对象被创建或者被回收的现象,同时内存抖动也可能会造成OOM,详见 https://blog.csdn.net/zhqw_csdn/article/details/80179119
                        ** 原因:主要是频繁(循环)创建对象,如果抖动很频繁会导致垃圾回收机制频繁运行,从而使UI现场被频繁阻塞,导致界面卡顿
                          ** 解决方案:1)尽量避免在循环体内创建对象,应该把对象创建移到循环体外
                                               2)自定义View的onDraw方法会频繁调用,所以在onDraw方法里不应该频繁创建对象
                                               3)当需要大量使用Bitmap的时候建议采用三级缓存LRUCache
                                               4)对于能够复用的对象,可以使用对象池缓存起来,比如对Fragment的缓存
            2.3:内存泄漏:详见 https://blog.csdn.net/zhqw_csdn/article/details/79899703

   3.线程优化:使用线程池对线程进行管理可以带来很多好处,首先通过线程池中线程的复用,可以减少创建和销毁线程带来的性能开销;其次,能控制线程池中线程的并发数,否则会因为大量的线程争夺CPU资源造成阻塞;最后,线程池能对线程进行管理,比如使用ScheduledThreadPool来设置延迟N秒后执行
        ** 线程池的创建:java里线程池的创建都是通过Executor来创建的,Executor是一个接口,Android里面的ExecutorService接口继承了该接口,ThreadPoolExecutor实现了该接口,可通过它构造java里面的4中线程池
                        ** 1.FixThreadPool(好比一堆人排队上厕所,厕所数量是固定不变的)
            ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())
                            *** 1)FixThreadPool只有核心线程,并且数量固定,也不会被回收,所有线程都活动时新任务等待执行
                            *** 2)由于线程不会被回收,所以FixThreadPool能更快的相应外界请求
                        ** 2.SingleThreadPool(厕所只有一个的情况)
            ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())
                            *** 1)因为只有一个核心线程,所以所有任务会在同一个线程中按顺序执行,不需要处理线程同步的问题
                        ** 3.CachedThreadPool(好比一堆人去一家很大的咖啡馆喝咖啡)
            ThreadPoolExecutor(0,10,60L,TimeUnit.MILLISECONDS,new new SynchronousQueue<Runnable>())
                            *** 1)SynchronousQueue相当于一个空集合,所以所有任务都会立即被执行
                            *** 2)比较适合执行大量的耗时少的任务,比如喝咖啡的人很多,喝的时间也不长
                        ** 4.ScheduledThreadPool(唯一一个有延迟执行和周期性重复执行的线程池)
            Executors.newScheduledThreadPool(int corePoolSize).scheduleAtFixedRate
                            *** 1)核心线程数固定,非核心线程没有限制,闲置线程会被立即回收
                            *** 2)ScheduledThreadPool主要用于执行定时任务以及周期性的任务
    4.精简app大小: 1)可以通过AndroidStudio自带的lint检测无用的代码,然后去掉无用的代码或者资源文件
                               2)有一些资源文件可以打包从服务端下载,比如音频资源,皮肤等
                               3)只使用1套图
                               4)必要的资源文件可以打成压缩包,使用的时候解压
    5.布局优化:主要就是减少布局嵌套,巧用merge+include,采用ViewStub在需要展示的时候才加载,避免过度绘制(PS:在    开发过程中如果View.INVISIBLE 和VIEW.GONE能够实现同样效果的话建议采用VIEW.INVISIBLE,因为VIEW.INVISIBLE控件还在,大小不发生变化,安卓系统不会重新测量控件,而VIEW.GONE控件大小发生了变化,安卓系统会重新测量控件)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值