性能优化

  1. 使用更加轻量的数据结构
    考虑使用Android专门的ArrayMap/SparseArray而不是HashMap等传统数据结构,SparseArray更加高效在于他们避免了对key与value的autobox自动装箱,并且避免了装箱后的解箱。
  2. 避免在Android里面使用Enum,使用enum比静态int省的dex大一倍。使用@Intdef
  3. 避免View的泄露导致Activity的泄露,2.3的Drawable4.0修复
  4. 复杂绘制开启硬件加速,SDK16开始属性动画可以直接开启:ViewPropertyAnimator.alpha().withLayer()
  5. bitmap优化1.解码格式ARGB_8888/RGB_565;2.缩放指定大小inScaled,inDensity,inTargetDensity;3.inbitmap;4.bitmappool
  6. 开启严格模式 Strict Mode,预防ANR
    7.自定义View1.ClipRect裁剪画布,2.Canvas.quickReject查找交叉区域
  7. AlarmManager、JobSchedulor定时任务
    9.发隐式Intent之前调用resolveActivity做检查
    10.提供了NotificationCompat兼容类来帮助开发实现体验统一的Notification参考
    11.使用MediaSessionCompat操作音乐的播放

限制应用的内存

为了整个Android系统的内存控制需要,Android系统为每一个应用程序都设置了一个硬性的Dalvik Heap Size最大限制阈值,这个阈值在不同的设备上会因为RAM大小不同而各有差异。如果你的应用占用内存空间已经接近这个阈值,此时再尝试分配内存的话,很容易引起OutOfMemoryError的错误。
ActivityManager.getMemoryClass()可以用来查询当前应用的Heap Size阈值,这个方法会返回一个整数,表明你的应用的Heap Size阈值是多少Mb(megabates)。

硬件加速

image.png

严格模式Strict Mode

UI线程被阻塞超过5秒,就会出现ANR,这太糟糕了。防止程序出现ANR是很重要的事情,那么如何找出程序里面潜在的坑,预防ANR呢?很多大部分情况下执行很快的方法,但是他们有可能存在巨大的隐患,这些隐患的爆发就很容易导致ANR。

Android提供了一个叫做Strict Mode的工具,我们可以通过手机设置里面的开发者选项,打开Strict Mode选项,如果程序存在潜在的隐患,屏幕就会闪现红色。我们也可以通过StrictMode API在代码层面做细化的跟踪,可以设置StrictMode监听那些潜在问题,出现问题时如何提醒开发者,可以对屏幕闪红色,也可以输出错误日志。下面是官方的代码示例:

public void onCreate() {
     if (DEVELOPER_MODE) {
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
     }
     super.onCreate();
}

自定义View

Android系统有提供超过70多种标准的View,例如TextView,ImageView,Button等等。在某些时候,这些标准的View无法满足我们的需要,那么就需要我们自己来实现一个View,这节会介绍如何优化自定义View的性能。

通常来说,针对自定义View,我们可能犯下面三个错误:

  • 我们知道调用View.invalidate()会触发View的重绘,有两个原则需要遵守,第1个是仅仅在View的内容发生改变的时候才去触发invalidate方法,第2个是尽量使用ClipRect等方法来提高绘制的性能。
  • 减少绘制时不必要的绘制元素,对于那些不可见的元素,我们需要尽量避免重绘。
  • 对于不在屏幕上的元素,可以使用Canvas.quickReject把他们给剔除,避免浪费CPU资源。另外尽量使用GPU来进行UI的渲染,这样能够极大的提高程序的整体表现性能。

最后请时刻牢记,尽量提高View的绘制性能,这样才能保证界面的刷新帧率尽量的高。更多关于这部分的内容,可以看这里

Bitmap图片相关

1.解码格式

所以为了避免加载一张超大的图片,需要尽量减少这张图片所占用的内存大小,Android为图片提供了4种解码格式,他们分别占用的内存大小如下图所示:


image.png

随着解码占用内存大小的降低,清晰度也会有损失。我们需要针对不同的应用场景做不同的处理,大图和小图可以采用不同的解码率。在Android里面可以通过下面的代码来设置解码率:


image.png
2.图片缩放:

对bitmap做缩放,这也是Android里面最遇到的问题。对bitmap做缩放的意义很明显,提示显示性能,避免分配不必要的内存。Android提供了现成的bitmap缩放的API,叫做createScaledBitmap(),使用这个方法可以获取到一张经过缩放的图片。

createScaledBitmap

上面的方法能够快速的得到一张经过缩放的图片,可是这个方法能够执行的前提是,原图片需要事先加载到内存中,如果原图片过大,很可能导致OOM。下面介绍其他几种缩放图片的方式。

inSampleSize能够等比的缩放显示图片,同时还避免了需要先把原图加载进内存的缺点。我们会使用类似像下面一样的方法来缩放bitmap:

inSampleSize
按幂级缩放

重要另外,我们还可以使用inScaled,inDensity,inTargetDensity的属性来对解码图片做处理,源码如下图所示:

android_perf_2_sacle_bitmap_inscale

还有一个经常使用到的技巧是inJustDecodeBounds,使用这个属性去尝试解码图片,可以事先获取到图片的大小而不至于占用什么内存。如下图所示:

android_perf_2_sacle_bitmap_injust

隐式Intent之前调用resolveActivity做检查参考

Intent intent = new Intent(Intent.ACTION_XXX);
ComponentName componentName = intent.resolveActivity(getPackageManager());
if(componentName != null) {
    String className = componentName.getClassName();
}

Notification兼容性问

为了解决Android系统版本差异导致的Notification兼容性问题,Android官方提供了NotificationCompat兼容类来帮助开发实现体验统一的Notification。通常来说,建立一个Notification至少会有三种元素:图标,标题,文本。我们通常会使用如下的代码来实现一个基础的Notification功能:

你可能感兴趣的:(性能优化)