APP性能优化系列—更优雅的延迟方案(四)

通过前几章的学习,大家已经掌握了在APP启动时,如何对一些第三方初始化的内容 使用启动器进行异步、同步及 使用有向无环图的拓扑排序处理继承关系等处理。这一章我们继续来探讨下在空闲期需要处理的Task。

还记得这张图吗?Application里面的各种第三方的初始化的分类。

我们通过第三章的学习 一线大厂大型APP性能优化系列-自定义启动器(三) 已经处理前4个,今天我们学习最后一个ilde task(延迟加载,空闲期处理方案)。

2.聊一聊假的延迟方案


(还是想吐槽,简历上都写着会APP的性能优化,一问,什么sendMessageDelayed,什么IldeHandler的定义使用背的都很熟练,再一问项目中怎么用的,基本都哑火了,就1个诚实的,直接回答,就那么用啊。。。emmmm。。。。所以不建议你们刷面经,至少高级岗位不建议,会露馅的)

在我们日常处理一些耗时任务的时候,有很多的方案,比如

1.可以通过Handler().sendMessageDelayed() 达到延迟加载。

原理:将消息加入队列中,然后MessageQueue会根据延时的时间进行队列的排序,时间最短的在前,
如果没有要执行的,就进行阻塞,阻塞的时间为最先要执行的任务的等待时间,如果不再添加新任务,则等时间到了会自动执行,如果添加了新任务,则重新排序,然后唤醒当前线程,将排序后,最先要执行的等待时间进行阻塞或者直接执行。

缺点:但是项目中是不建议这样用的,因为会强占CPU,性能会进行耗损,比如一个页面的一些第三方服务进行初始化操作,虽然说是可以延迟一段时间再去初始化,但是如果该页面一直在执行,比如有个定时器或者轮询请求接口等,那么到了时间,依然是要强占CPU来执行我们的第三方服务的初始化操作。所以不能直接这么用

不知道会不会有杠精,“我们平时也是这么用的呀,也没问题呀”。但是你要记住,我聊的是大型项目,比如中石油终端,一个APP中,不光要作为主设备接收其他设备传递的数据,保持的长链接,还通过自定义的一些协议,比如FTFS协议,与硬件进行连接,如加油机,前庭控制器,液位仪等,你直接来个延迟初始化,一开始没什么,等延迟时间到了,如果人员也在操作,油机也在实时上报数据,直接卡死你。

2.IldeHandler

这个的确能解决我们之前尴尬的问题,它的主张是在CPU空闲时再进行操作,不抢占CPU

同学们,面经是不是就只写到这呀,那你们考虑过,如果请求过多尼,如果并发尼?如果空闲执行中执行的任务还必须有先后执行的顺序尼。比如A页面,B页面都把自己耗时的方法加入到了空闲执行队列里面,但是要想执行B页面耗时方法,必须得先执行页面A中的方法,你该怎么做?

废话不多说,直接上代码,顺便附一张之前战斗过的地方,项目虽好,但是工作室太“简陋”,做完几个版本就溜了。。

3.聊一聊IdleHandler的优化及封装


不知道task是啥的,就去看第三章内容。

/**

  • @author: lybj

  • @date: 2020/5/26

  • @Description: 空闲队列

*/

public class IldeTaskDispatcher {

private Queue mIldeQueue = new LinkedList<>();

private MessageQueue.IdleHandler messageQueue = new MessageQueue.IdleHandler(){

@Override

public boolean queueIdle() {

if(mIldeQueue.size() > 0){

// 如果CPU空闲了,

Task IldeTask = mIldeQueue.poll();

new DispatchRunnable(IldeTask).run();

}

// 如果返回false,则移除该 IldeHandler

return !mIldeQueue.isEmpty();

}

};

public IldeTaskDispatcher addTask(Task task){

mIldeQueue.add(task);

return this;

}

/**

  • 执行空闲方法,因为用了DispatchRunnable,所以会优先处理需要依赖的task,再处理本次需要处理的task,顺序执行

  • */

public void start(){

Looper.myQueue().addIdleHandler(idleHandler);

}

}

调用的话也很简单

new IldeTaskDispatcher()

.addTask(new InitBaiduMapTask())

.addTask(new InitBuglyTask())

.start();

4.其他代码


不明白的,去看上一章的讲解,这章本来就是在上一章内容上增加的拓展

DispatchRunnable

public class DispatchRunnable implements Runnable {

private Task mTask;

private TaskDispatcher mTaskDispatcher;

public DispatchRunnable(Task task) {

this.mTask = task;

}

public DispatchRunnable(Task task,TaskDispatcher dispatcher) {

this.mTask = task;

this.mTaskDispatcher = dispatcher;

}

@Override

public void run() {

Process.setThreadPriority(mTask.priority());

long startTime = System.currentTimeMillis();

mTask.setWaiting(true);

mTask.waitToSatisfy();

long waitTime = System.currentTimeMillis() - startTime;

startTime = System.currentTimeMillis();

// 执行Task

mTask.setRunning(true);

mTask.run();

// 执行Task的尾部任务

Runnable tailRunnable = mTask.getTailRunnable();

if (tailRunnable != null) {

tailRunnable.run();

}

if (!mTask.needCall() || !mTask.runOnMainThread()) {

printTaskLog(startTime, waitTime);

TaskStat.markTaskDone();

mTask.setFinished(true);

if(mTaskDispatcher != null){

mTaskDispatcher.satisfyChildren(mTask);

// --> 8

mTaskDispatcher.markTaskDone(mTask);

}

}

TraceCompat.endSection();

}

}

task

public abstract class Task implements ITask {

private volatile boolean mIsWaiting; // 是否正在等待

private volatile boolean mIsRunning; // 是否正在执行

private volatile boolean mIsFinished; // Task是否执行完成

private volatile boolean mIsSend; // Task是否已经被分发

// 当前Task依赖的Task数量(需要等待被依赖的Task执行完毕才能执行自己),默认没有依赖

private CountDownLatch mDepends = new CountDownLatch(dependsOn() == null ? 0 : dependsOn().size());

/**

  • 依赖的Task执行完一个

*/

public void satisfy() {

mDepends.countDown();

}

/**

  • 当前Task等待,让依赖的Task先执行

*/

public void waitToSatisfy() {

try {

mDepends.await();

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-ImqSXVl5-1719049580975)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取
oid waitToSatisfy() {

try {

mDepends.await();

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-ImqSXVl5-1719049580975)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值