目录
内存抖动的定义
内存频繁地分配和回收,它伴随着频繁的GC。
内存泄漏和内存抖动的影响
内存泄漏:可用内存越来越少 -> OOM
内存抖动:
1.卡顿(进行垃圾回收的时候,其他线程会被挂起,比如点击一个按钮,但是在进行gc操作,ui线程被挂起,无法响应点击事件)
2.OOM(如果使用标记-清除算法的话,频繁的进行垃圾回收会导致内存碎片化,连在一起的内存不足以分配给新的对象的时候就会报OOM)
避免内存抖动(避免在很频繁调用的方法中创建对象)
1.很频繁调用的方法中创建对象,可以将创建对象的代码放在方法外。
2.很频繁调用的方法中创建对象,但是这个对象不能定义成全局的,例如Handler中的Message(消息队列)这种就不能用第一种方法解决。第一个message进入消息队列等待出队,这时第二个message直接复用第一个message的对象进行修改,那么消息队列中的message也会被相应的修改掉。这里的解决办法是使用自定义缓冲池来解决每次都需要新建对象的问题。(a.使用链表定义无差别对象池,类Message; b.使用LRU最近最少使用算法和红黑树实现有差别对象池)
3.很频繁调用的方法中创建对象,使用gson.fromJson(),gson.fromJson()会通过反射创建对象,解决办法是:可以使用gson的建造者模式进行创建gson
val gson= GsonBuilder().registerTypeAdapter(CacheLinkTestGsonBean::class.java,TestTypeAdapter()).create()
for (i in 1..1000){
val d= gson.fromJson<CacheLinkTestGsonBean>("{\"name\"=\"kaylee${i}\"}",CacheLinkTestGsonBean::class.java)
Log.i("DealGsonFromJsonActivity",d.name)
}
其中CacheLinkTestGsonBean是实现了缓存的自定义缓存池
package com.example.myapplication.gson_fromJson
import android.util.Log
import android.widget.Toast
//类似Message通过链表实现缓存池
class CacheLinkTestGsonBean {
var name:String=""
var next: CacheLinkTestGsonBean? = null//链表的下一个元素
companion object {
private var sPoolSize = 0//对象池中现有的对象数
private val MAX_POOL_SIZE = 10//对象池的最大长度
private val sPoolSync = Any()//对象锁
private var sPool: CacheLinkTestGsonBean? = null//链表第一个元素(代表对象池)
fun obtain(): CacheLinkTestGsonBean {
synchronized(sPoolSync) {
if (sPool != null) {
val c: CacheLinkTestGsonBean = sPool!!
sPool = c.next
c.next = null
sPoolSize--
Log.i("CacheLink","从对象池取对象sPoolSize")
return c
}
}
Log.i("CacheLink","新建对象")
return CacheLinkTestGsonBean()
}
}
fun recycle() {
synchronized(sPoolSync) {
if (sPoolSize <MAX_POOL_SIZE) {
next = sPool
sPool = this
sPoolSize++
Log.i("CacheLink","当前PoolSize${sPoolSize}")
}
}
}
}
其中TestTypeAdapter定义了读写方法,这里是解决内存抖动的关键
package com.example.myapplication.gson_fromJson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
class TestTypeAdapter : TypeAdapter<CacheLinkTestGsonBean>(){
override fun write(out: JsonWriter?, value: CacheLinkTestGsonBean?) {
out?.beginObject()
out?.name(value?.name)
out?.endObject()
}
override fun read(`in`: JsonReader?): CacheLinkTestGsonBean {
//这里不会直接创建对象,改为从对象池中获取
val testGsonBean=CacheLinkTestGsonBean.obtain()
if (`in`!=null) {
`in`.beginObject()
while (`in`.hasNext()) {
if (`in`.nextName()=="name") {
testGsonBean.name = `in`.nextString()
}
}
`in`.endObject()
}
testGsonBean.recycle()
return testGsonBean
}
}
项目地址:GitHub - iamzhangjunhui/LearnDemoApplication
参考:https://www.bilibili.com/video/BV1mR4y1x7ks?spm_id_from=333.999.0.0