Android性能优化建议

94 篇文章 0 订阅
94 篇文章 0 订阅

磁盘

SharedPreferences

我们知道SharedPreferences底层是使用xml文件来实现的。所以对于SharedPreferences的操作其实是I/O操作,是耗时操作。

commit

每一次commit的调用都会对应一次文件的打开和关闭。commit是同步操作,apply是异步操作。

最佳实践

减少commit的次数; 在一个逻辑操作(方法)中不要多次commitcommit应放在最后。或者使用缓存来保存多次写入的数据,最后提交commit

如果对数据的实时性没有要求,可以使用apply来代替commit

flag的保存与使用

我们通常会使用SharedPreferences来保存一些flag。但是要注意不要随意使用。比如你在一个Recycleview的卡片中,根据一个flag来做不同UI的判断:

class SimpleCard : LinearLayout, AdapterItem{
    fun bindData(...){
        if(Sp.getBoolean(xxx)){
            ...
        }    
    }
}

因为SimpleCardRecycleview中频繁被bindData, 因此SP.getBoolean(xxx)会被频繁调用,前面已经说了SP的读或写是io操作。这种写法势必会造成UI卡顿。

最佳实践

flag一般来说在app启动的时候就已经确定了,所有我们只需要获取一次。可以提前初始化这些flag:

//比如在某个Activity的onCreate

    runOnIoThread({
        FlagCenter.initAllFlag()
    })

//SimpleCard.bindData

 fun bindData(){
        if(FlagCenter.useStyle1){
            ...
        }
    }

ObjectOutputStream

利用它我们可以把对象保存到磁盘中。不过它有一个特点:在保存对象的时候,每个数据成员会带来一次I/O操作。因此如果你对象很多、属性很复杂时,ObjectOutputStreamI/O操作会异常凶猛。

最佳实践

最好在ObjectOutputStream上再封装一个输出流,比如BufferedOutputStream。先把对象写入到这个流中,然后再使用ObjectOutputStream保存到磁盘。

合理设置buffer

在读一个文件我们一般会设置一个buffer。即先把文件读到buffer中,然后再读取buffer的数据。所以: 真正对文件的次数 = 文件大小 / buffer大小 。 所以如果你的buffer比较小的话,那么读取文件的次数会非常多。当然在写文件时buffer是一样道理的。

很多同学会喜欢设置1KB的buffer,比如byte buffer[] = new byte[1024]。如果要读取的文件有20KB, 那么根据这个buffer的大小,这个文件要被读取20次才能读完。

最佳实践 -> buffer应该设置多大呢?

java默认的buffer为8KB,最少应该为4KB。那么如何更智能的确定buffer大小呢?

  1. buffer的大小不能大于文件的大小。
  2. buffer的大小可以根据文件保存所挂载的目录的block size, 什么意思呢? 来看一下SQLiteGlobal.java是如何确定buffer大小的 :
public static int getDefaultPageSize() { 
    return SystemProperties.getInt("debug.sqlite.pagesize", new StatFs("/data").getBlockSize());
}

Bitmap的解码

在Android4.4以上的系统上,对于Bitmap的解码,decodeStream()�的效率要高于decodeFile()decodeResource(), 而且高的不是一点。所以解码Bitmap要使用decodeStream(),同时传给decodeStream()的文件流是BufferedInputStream

最佳实践

val bis =  BufferedInputStream(FileInputStream(filePath))
val bitmap = BitmapFactory.decodeStream(bis,null,ops)

内存

在虚拟机的Heap内存使用超过堆内存最大值就会发生OOM。当手机内存低于内存警戒线时,占用内存越多的APP越有可能被Low Memory Killer给杀掉。

内存泄漏

Activit内存泄漏

Activity对象会间接或者直接引用View、Bitmap等,所以一旦无法释放,会占用大量内存。并且Activity在Destroy的情况下,更新UI是会引发crash的。而Activity内存泄漏最常见的就以下几种case:

  1. 生命周期比Activtiy长的对象持有了Activity的引用。比如在getSystemService时使用了Activity

  2. Activity的内部类作为一个异步的回调监听。比如定义了一个Handler内部类,这时候Handler默认就会引用Activity

最佳实践

在使用getSystemService方法时尽量使用Application, 比如: applicationContext.getSystemService(Context.INPUT_METHOD_SERVICE)

Activity中的Handler定义为静态内部类(解除对Activity的引用),并使用WeakReference<Activity>来引用Activity。

图片

Feed流中的图片如果可以应尽可能降低所占内存大小

对于要加载的图片应做压缩,并在适当的情况下可以在解码时降低质量

最佳实践

对于无透明效果、比较小的图片可以使用RGB_565格式来解码。

在设置解码图片的inSmapleSize参数时应参考要显示的View的宽与高来显示恰当的值。

图片资源不要放在错误的目录

Android的drawable分为好几个层级,比如:drawable、drawable-hdpi、drawable-ldpi、drawable-mdpi等,其实就是对应不同的屏幕密度。Android在获取某个屏幕密度的图片时会去对应的drawable目录下寻找,如果找不到就会取相近目录的资源。但这里是存在一个问题的,举个例子:

比如一张 800 * 480 的图片放置在了ldpi目录。如果480dpi(xxxhdpi)的屏幕要显示这张图片,那么他就会把这张图片放大4倍,即 3200 *1920,然后再去解码。所以图片在内存中被放大了4倍。如果这种case多了,内存很容易爆掉的。

最佳实践

尽量问设计师要高品质图片然后放在高密度目录下,这样在低密度上放大倍数是小于1的,在保证画质的前提下,内存也是可控的。

SparseArray与ArrayMap

SparseArray也是一个map,它的key必须为int类型, 在数据量不大的情况下(千级以内),它的性能会要比HashMap好,并且更升内存。

SparseArray与ArrayMap的key可以为任意类型,当数据量比较小时也可以使用它来代替HashMap

 

 

+qq群:853967238。获取以上高清技术思维图,以及相关技术的免费视频学习资料。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
赵子健是知名的 Android 专家,他在性能优化方面也有很多经验。以下是他在 Android 性能优化方面的一些建议: 1. 减少内存分配:内存分配是 Android 应用程序中的一个性能瓶颈,过多的内存分配会导致频繁的垃圾回收和系统卡顿。因此,应该尽量减少内存分配,比如使用对象池、避免频繁的创建和销毁对象等。 2. 使用异步任务:在 Android 应用程序中,如果主线程(UI 线程)执行耗时操作,会导致应用程序卡顿或者 ANR。因此,应该使用异步任务来执行耗时操作,比如使用 AsyncTask、HandlerThread、ThreadPoolExecutor 等。 3. 优化布局:布局也是 Android 应用程序中的一个性能瓶颈,过于复杂的布局会导致 UI 渲染变慢,甚至卡顿。因此,应该尽量简化布局,避免嵌套过深、避免不必要的布局文件等。 4. 避免过度绘制:Android 应用程序中的另一个性能瓶颈是过度绘制。过度绘制是指在同一个区域内反复绘制,导致不必要的 CPU 和 GPU 资源消耗。因此,应该避免过度绘制,比如使用 setWillNotDraw() 方法、使用硬件加速等。 5. 使用工具进行优化:Android 中有很多性能优化工具,比如 TraceView、Systrace、HierarchyViewer 等,可以帮助开发者找到应用程序中的性能瓶颈,进行优化。 以上是赵子健在 Android 性能优化方面的一些建议,当然还有很多其他的优化技巧和工具,需要根据实际情况进行选择和应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值