当前位置: 首页 > 后端技术 > Java

Android性能优化

时间:2023-04-01 18:14:44 Java

Android性能优化一:简介Android性能优化主要集中在以下四个方面:1.稳定性(内存溢出,崩溃)2.流畅性(卡顿)3.损耗(功耗,流量)4.安装影响包稳定性(APK瘦身)的因素有很多,比如内存使用不合理、代码异常场景不合理、代码逻辑不合理等,都会影响应用的稳定性。最常见的两种场景:Crash和ANR,这两种错误都会导致程序无法正常使用。1、因此,做好Crash全局监控,处理crash并收集记录crash信息和异常信息,以便后续分析;2、合理使用主线程处理业务,不要在主线程中做耗时操作,防止ANR程序超时。响应发生。内存是Android运行性能的一个重要指标,每个进程能够使用的内存是有限的。不合理的使用内存会导致频繁的GC甚至OOM。过多的GC会导致App卡死,内存泄漏或者内存抖动会导致OOM,这是不可接受的。二:稳定(内存溢出、崩溃)内存泄漏:长期持有对象的引用会导致内存占用过多,导致应用卡顿;意味着程序不再使用的对象不能被GC识别,这就导致这个对象一直停留在内存中,在它来之前占用了大量的内存空间。1.单例模式导致的内存泄漏与单例模式的生命周期和app生命周期一致publicclassSingleton{privateContextcontext;私有静态单例mInstance;privateSingleton(Contextcontext){this.context=context;}publicstaticSingletongetInstance(Contextcontext){if(mInstance==null){mInstance=newSingleton(context);}返回mInstance;}}//这是标准的单例模式写法,表面上没有问题,但是细心的同学会发现,在构造单例的实例时,需要传入一个Context。这时候,传入的Context非常关键。如果此时传入的是一个Activity,由于Context会一直被创建的实例持有,当Activity进入后台或者在设置中启用非保留activity时,Activity会被销毁,但是单例持有它的上下文引用,Activity无法销毁,导致内存泄漏。//如果此时传入的Context是ApplicationContext,由于ApplicationContext的生命周期与app是一致的,所以不会造成内存泄漏。但是我们不能指望使用这个单例的用户总是传入预期的Context,所以我们需要调整这个单例的设计。您可以在构造函数中将mContext分配给this.mContext=context.getApplicationContext;当然你也可以直接不让用户传入上下文。当我们在Activity中使用this的时候,传入我们的Acitivty上下文,那么这个单例会持有这个Activity的引用,当这个Activity没用需要销毁的时候,因为这个单例还持有Activity的引用不能被GC回收,所以发生内存泄漏,即长生命周期的引用持有短生命周期的引用,导致内存泄漏。2.非静态内部类持有外部类的引用导致内存泄漏内部类的生命周期可能比外部类的生命周期长,和二楼的情况一样。如果非静态内部类的周期比外部类长,再加上自动持有的外部类的强引用,亲,想不漏都难。公共类TestActivity扩展活动{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_test);新的MyAscnyTask().execute();静态类MyAscnyTask扩展AsyncTask{@OverrideprotectedStringdoInBackground(Void...params){try{Thread.睡眠(100000);}catch(InterruptedExceptione){e.打印堆栈跟踪();}返回””;}}}3.Handler引起的内存泄漏。我们知道Handler、Message、MessageQueue是相互关联的。Handler通过发送Message与主线程进行交互。如果Handler发送的消息Message没有被处理,Message和发送它的Handler对象会一直被MessageQueue持有,可能会导致Handler回收失败。将Handler声明为静态内部类,不会持有对外部类SecondActivity的引用,其生命周期与外部类无关。如果Handler中需要上下文,可以通过弱引用来引用外部类。其实Handler也是非静态内部类的问题导致的。它会持有Activity的引用,发送延时消息,但是Activity已经关闭,所以一直持有Activity的引用,无法处理消息。publicclassScanActivityextendsAppCompatActivity{//改为静态内部类,防止内存泄露Stringaa=(String)msg??.obj;Log.d("aa",aa);System.out.println(aa);}};@OverrideprotectedvoidonCreate(@NullableBundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_four);消息message=消息.obtain();message.obj="你好";mHandler.sendMessage(消息);mHandler.sendMessageDelayed(message,10000);//如果要发送延迟消息,同时跳转到其他页面,会导致消息队列中一直持有activity引用的内存泄漏//所有的改进方法都是将Handler的内部类改为静态内部类}}4.资源对象没有关闭,造成内存泄漏在android中,资源对象如Cursor、File、Bitmap、video等,系统使用了一些缓冲技巧。在使用这些资源的时候,如果保证不再使用这些资源,一定要及时关闭它们,否则可能会造成内存泄漏。因为有些操作不仅涉及到Dalvik虚拟机,还涉及到底层C/C++的内存管理等,我们不能完全寄希望于虚拟机帮我们完成内存管理。在开发过程中,我们经常会在Activity的onCreate中注册广播接收器、EventBus等。如果忘记成对使用反注册,可能会造成内存泄漏。开发过程中要养好关系,在onCreate或onResume中注册,记住onDestroy或onPause中对应的反注册内存泄漏是对对象的引用,那么引用分为强引用,软引用,weakreference,Phantomreferences和strongreferences一般都是我们平时不做特殊处理的强引用。如果一个对象有强引用,GC宁愿OOM也不愿回收。看看它有多艰难。软引用(SoftReference)如果内存空间足够,GC是不会回收的。如果内存空间不足,就会回收这些对象的内存。弱引用(WeakReference)弱引用是比软引用弱一级。如果没有足够的内存,它们必须被回收。在GC的时候,无论内存是否足够,都必须回收。简直就是弱者。不过GC是一个优先级很低的线程,执行的也不是太频繁,所以弱引用的寿命还是过得去的,没那么担心。虚假引用很少使用,我也从未使用过。如果想了解更多,可以自行google百度。内存泄漏分析工具1.leakcanary傻瓜式操作,哪里有泄漏就会自动显示给你,非常直接和暴力。(有待研究)2.我们通常使用MemoryMonitor来进行内存监控。这个分析有点难。您可以在Internet上搜索有关如何使用它的详细信息。三:快(流畅,卡顿)1.布局优化屏幕上的某个像素在同一帧内被多次绘制。在多级UI结构中,如果不可见的UI也在做绘制操作,这会导致一些像素区域被绘制多次。这会浪费大量的CPU和GPU资源。如果父控件有颜色,也是你需要的颜色,那么就不需要给子控件添加背景色。如果每个子控件的颜色都不同,并且可以完全覆盖父控件,那么就不需要给父控件添加背景色。尽量减少不必要的嵌套。可以使用LinearLayout和FrameLayout代替RelativeLayout,因为RelativeLayout控件相对复杂,映射起来比较费时。使用include和merge来增加多路复用并减少层数。ViewStub可以按需加载,以获得更便携和复杂的界面。可以选择ConstraintLayout,可以有效减少层数。2.绘图优化这是Android的渲染机制造成的。渲染UI,但可能渲染不成功。如果成功了,说明一切顺利,但是如果失败了,可能会耽误时间,或者直接跳过,给人一种视觉上的表现,就是要么卡一会,要么跳帧。最好保证View的绘制频率为60fps,这就要求每一帧的绘制时间不超过16ms(16ms=1000/60)。虽然程序很难保证16ms的时间,但是在onDraw方法中尽量降低复杂度总是可行的。有效的。然后在ondraw()方法中绘制,不要在onDraw方法中新建局部对象。不要在onDraw方法中做耗时任务4:功耗优化在定位精度不高的情况下,使用wifi或者移动网络定位,不需要开启GPS定位。先验证网络是否可用,再发送网络请求。例如,当用户处于2G状态,此时的操作是查看大图,那么下载量可能会超过200K甚至更大。我们不需要发送此请求。让用户静候那菊花。适当做本地缓存,避免频繁请求网络数据。在这里,说起来容易,做起来却不容易。需要配合好的缓存策略,区分哪些是一段时间内不会变的,哪些是绝对不能变的。缓存很重要。五:安装包(Apk瘦身)1.so库优化大多数情况下只需要支持armabi和x86架构即可。如果不需要,可以考虑去掉部分x86ndk{//设置支持的so库架构abiFilters"armeabi"}2.去掉无用资源END:路漫漫其修远兮