抖音优化的思路
咱们着重看 这一部分
尽管没有代码,可是文字描述的也够清楚了,咱们能够总结概括一下,抖音的优化思路 ,然后就能够尝试去完结它了
1.acitivity 跳转的 生命周期 音讯 是能够 进行优化的 ,说白了 便是 让这些生命周期音讯 的优先级进步 ,尽早的让他履行
-
要提升doFrame的音讯优先级, 这儿其实用音讯屏障 就能够完结,这个咱们后面再说, 这儿就只要知道 这个优化 能够进步首帧烘托 速度即可
-
自定义Printer 是要害, 这个应该做过主线程音讯卡顿监听的同学 都很了解了。
-
在这个自定义Printer中 遍历音讯类型 就能够完结上述的优化思路
-
一定得在音讯处理完毕之后 再调整音讯次序, 这个其实仔细想想就理解为啥要这么做,
能够参阅 得物的完结 ,该文章是拿Observer去完结的,有android版别的限制,尤其是一些hidden api,用起来比较麻烦,可是思路是很棒的,有兴趣的能够多看看。
我这儿便是基于Printer这个接口来完结了,没什么hidden api 需要处理。
Activity 跳转音讯流程
<=android8
在android的老版别中 activity的页面跳音讯
主要重视下 message的what的值即可
记住这个100和101的值,后续咱们会用到
>=android9
而从android9 开始 页面的跳转音讯 就变成了 excute_transaction
继续跟一下,留意这个常量值
关于activity 生命周期的音讯 其实便是封装在 这个activitylifecycleitem 这个类中
咱们其实最重视的便是
到这儿咱们就搞清楚了 >=android9.0 的 页面跳转音讯的 类型
joor 反射库
由于这次需要反复利用反射来做许多事情,为了简略 咱们运用joor反射库 来做,具体就不介绍用法了,自行google
获取activityThread中的 handler
已然要调整音讯的次序,咱们天然要用到handler,而且有必要是activityThread中的 handler,去源码中找一下
找到今后 无非便是反射 拿到这个handler罢了
这个其实没啥难度
mainHandler = Reflect.onClass("android.app.ActivityThread").field("sCurrentActivityThread").field("mH").get()
有了他,咱们就能够发送各种音讯 让ActivityThread 去处理啦
一些基本处理
首先要定义一组变量 其实便是为了判别是不是跳转类型的音讯
class FakeActivityLifecycleItem {
companion object {
// public static final int EXECUTE_TRANSACTION = 159;
const val EXECUTE_TRANSACTION = 159
const val ON_PAUSE = 4
const val ON_RESUME = 3
const val LAUNCH_ACTIVITY = 100
const val PAUSE_ACTIVITY = 101
}
}
然后 咱们就要从looper中 获得这个queue,然后取到message,用while循环的方法 来遍历这个音讯列表中的音讯,判别类型, 这儿代码简略 就不过多讲了,
if (log?.contains("Finished to Handler") == true) {
// 获取主线程的queue
val mainMsg = Looper.getMainLooper().queue
// 获取第一个音讯
var message: Message? = Reflect.on(mainMsg).field("mMessages").get()
// 获取前一个音讯
var preMessage: Message? = null
// 记载该音讯 在本来链表中的第几个方位
var index = 0
// 遍历音讯链表
while (message != null) {
// 由于音讯中心 是一个链表,所以 要调整次序 必然涉及到 preMessage的指针 改动
if (preMessage != null) {
}
preMessage = message
message = (Reflect.on(message).field("next").get())
index++
}
进步页面跳转音讯的优先级
有了前面的基本循环今后 便是考虑怎么调整音讯优先级
- 找到对应的jump类型的音讯
- 把这个音讯放到行列头部去
- 由于你把音讯放到行列头部了,所以你有必要把 message的preMsg 的next指针 指向 message的下一个next即可 不然你行列中就有重复的音讯了,这儿千万不要忘记了。
其实便是一个很简略的 链表删去
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
// android8 以下
if (message.what == FakeActivityLifecycleItem.LAUNCH_ACTIVITY ||
message.what == FakeActivityLifecycleItem.PAUSE_ACTIVITY
) {
val copyJumpMsgAndroid8 = Message.obtain(message)
// 这儿一定要设置异步音讯
if (message.isAsynchronous) {
copyJumpMsgAndroid8.isAsynchronous = true
}
val nextMessage = Reflect.on(message).field("next").get<Message>()
Reflect.on(preMessage).set("next", nextMessage)
// 将要害的音讯放到行列头部去履行
mainHandler?.sendMessageAtFrontOfQueue(copyJumpMsgAndroid8)
break
}
} else {
// android9 及 以上
if (message.what == FakeActivityLifecycleItem.EXECUTE_TRANSACTION) {
val sr = Reflect.on(message.obj).field("mLifecycleStateRequest").call("getTargetState").get<Int>()
if (sr == FakeActivityLifecycleItem.ON_PAUSE || sr == FakeActivityLifecycleItem.ON_RESUME) {
val copyJumpMsgAndroid9 = Message.obtain(message)
if (message.isAsynchronous) {
copyJumpMsgAndroid9.isAsynchronous = true
}
Log.e("lixiao", "preMessage!=null result:$sr index:$index")
val nextMessage = Reflect.on(message).field("next").get<Message>()
Reflect.on(preMessage).set("next", nextMessage)
// 将要害的音讯放到行列头部去履行
mainHandler?.sendMessageAtFrontOfQueue(copyJumpMsgAndroid9)
break
}
}
}
进步首帧表现
能够要点参阅同步屏障
这篇文章的阐明
讲白了,你要进步doFrame的优先级,便是要想办法 进步同步屏障音讯的优先级
if (message.target == null) {
val copy = Message.obtain(message)
val success = mainHandler?.sendMessageAtFrontOfQueue(copy)
// 这儿千万不要忘记
copy.target = null
if (success == true) {
val next = Reflect.on(message).field("next").get<Message>()
Reflect.on(preMessage).set("next", next)
Reflect.on(message).set("next", null)
break
} else {
break
}
}