原理
字节跳动SP优化方案
方案
根据字节跳动的文章和Android源码分析可知,SP的apply方法会将每一次的apply做成一个任务去执行,然后添加到Activity的sPendingWorkFinishers去执行。 分析Android11的源码可知,apply()方法之后,代码就开始执行了。如果我们等待片刻,onStop的时候就会发现,finish队列已经空了,并不会引起ANR。什么时候会引起ANR?当apply加入后的finish队列还没执行完我们就退出时才会ANR或者卡顿,根本问题就是主线程等待SP的存储线程完成才退出详见: 而触发wait的条件就是
解决方案
根据原文提供的方案,我们就是动态替换,finish的List,然后poll方法返回空即可,代码如下
private static String CLASS_QUEUED_WORK = "android.app.QueuedWork";
private static String FIELD_PENDING_FINISHERS = "sPendingWorkFinishers";
public static void getPendingWorkFinishers() {
try {
Class clazz = Class.forName(CLASS_QUEUED_WORK);
Field field;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
field = clazz.getDeclaredField(FIELD_PENDING_FINISHERS);
} else {
field = clazz.getDeclaredField("sFinishers");
}
field.setAccessible(true);
Object o = field.get(null);
ConcurrentLinkedQueueProxy a = new ConcurrentLinkedQueueProxy((LinkedList) o);
field.set(null, a);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}
import java.util.*
class ConcurrentLinkedQueueProxy<E> : LinkedList<E> {
constructor(c: LinkedList<E>) {
this.addAll(c)
}
override fun poll(): E? {
return null
}
override fun isEmpty(): Boolean {
return true
}
}
以上代码已适配Android11 其他版本因为没有机型没有适配。断点自己处理即可
|