徐州免费网站建设如何在百度上营销

当前位置: 首页 > news >正文

徐州免费网站建设,如何在百度上营销,常州建设工程信息网,黑色 网站背景#xff1a; 经常在做一些app冷启动速度优化等性能优化工作时候#xff0c;经常可能会发现有时候需要引入一些第三方sdk#xff0c;或者库#xff0c;这些库一般会要求我们在onCreate中进行初始化等#xff0c;但是onCreate属于生命周期的回调方法#xff0c;如果on…背景 经常在做一些app冷启动速度优化等性能优化工作时候经常可能会发现有时候需要引入一些第三方sdk或者库这些库一般会要求我们在onCreate中进行初始化等但是onCreate属于生命周期的回调方法如果onCreate中业务过多就会影响整个app的冷启动时长很多人这个时候第一想到可能是放入子线程等但是经常又发现有的调用还要求在主线程调用等限制所以针对这种情况下就经常会使用到一个IdleHandler这个当初使用时候大家可能就只是字面意思理解为空闲的Handler在空闲时候执行其实没有深入去看看它到底实现原理是什么今天刚好有机会就来给大家进行一个剖析。 IdleHandler 的概念 IdleHandler 是 MessageQueue 提供的一个接口用于监听消息队列的空闲状态。它允许开发者在主线程处于空闲时执行一些低优先级的任务。IdleHandler 的核心方法 queueIdle() 会在系统检测到消息队列空闲时调用。返回值决定了 IdleHandler 是否继续在队列中保留若返回 true则该回调在下次队列空闲时继续执行反之返回 false 则表示仅执行一次后移除。 IdleHandler 和性能优化 IdleHandler 的出现正好迎合了性能优化的需求。在实际开发中有一些任务并非必须实时完成例如日志上报、资源预加载、缓存清理、数据统计、一些动画或预渲染任务等。利用 IdleHandler可以将这些不紧急的任务推迟到主线程消息队列空闲时再执行从而避免干扰用户看到的实时界面更新提高整体界面流畅度和响应速度。因此在 UI 主线程相对繁忙时通过 IdleHandler 来分摊任务可以让系统先处理用户的核心交互就比如onCreate是生命周期方法如理里面初始化太多东西影响冷启动速度针对一些可以延后不那么紧急任务可以待系统空闲时再处理任务充分利用 CPU 空闲时间。 源码分析IdleHandler 为了更加全面了解IdleHandler下面将要从以下几个部分进行IdleHandler的源码分析。 1、 IdleHandler的接口解释 frameworks/base/core/java/android/os/MessageQueue.java /*** Callback interface for discovering when a thread is going to block* waiting for more messages./public static interface IdleHandler {/** Called when the message queue has run out of messages and will now* wait for more. Return true to keep your idle handler active, false* to have it removed. This may be called if there are still messages* pending in the queue, but they are all scheduled to be dispatched* after the current time./boolean queueIdle();}上面注释就可以看出来这个IdleHandler属于一个回调接口这个接口在线程即将要阻塞等待更多消息时候会被调用。 queueIdle就是对应的回调函数这个queueIdle有一个返回值true或false这两个值分别有如下区别 如果返回true意味着下一次空闲依旧会执行这个IdleHandler的回调函数。 如果返回false就代表当前IdleHandler已经执行完毕下次空闲不会再执行该IdleHandler。 添加IdleHandler接口 /** Add a new {link IdleHandler} to this message queue. This may be* removed automatically for you by returning false from* {link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is* invoked, or explicitly removing it with {link #removeIdleHandler}.** pThis method is safe to call from any thread.** param handler The IdleHandler to be added.*/public void addIdleHandler(NonNull IdleHandler handler) {if (handler null) {throw new NullPointerException(Cant add a null IdleHandler);}synchronized (this) {//这里其实就是加入到mIdleHandlers这个集合中mIdleHandlers.add(handler);}}这里的addIdleHandler添加就是简单加入的mIdleHandlers这个集合中方便后面执行时候进行遍历 IdleHandler的触发执行 UnsupportedAppUsageMessage next() {int pendingIdleHandlerCount -1; // -1 only during first iterationint nextPollTimeoutMillis 0;for (;;) {//进入等待消息要被唤醒2种情况1被其他函数wake2等待时间nextPollTimeoutMillis到nativePollOnce(ptr, nextPollTimeoutMillis);synchronized (this) {// Try to retrieve the next message. Return if found.final long now SystemClock.uptimeMillis();Message prevMsg null;Message msg mMessages;//当消息的Handler为空时则查询异步消息if (msg ! null msg.target null) {// Stalled by a barrier. Find the next asynchronous message in the queue.//当查询到异步消息则立刻退出循环do {prevMsg msg;msg msg.next;} while (msg ! null !msg.isAsynchronous());}if (msg ! null) {//检测msg时间是还没到了if (now msg.when) {// Next message is not ready. Set a timeout to wake up when it is ready.//还没到msg的处理时间那么就会与当前时间进行差值这个差值就是等待时间nextPollTimeoutMillisnextPollTimeoutMillis (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else {// Got a message.mBlocked false;if (prevMsg ! null) {prevMsg.next msg.next;} else {//设置下一个消息为mMessagesmMessages msg.next;}msg.next null;msg.markInUse();//直接return回去消息也就是有消息都在这里return了不会执行下面业务return msg;}} else {//没有找到消息// No more messages.nextPollTimeoutMillis -1;}// If first time idle, then get the number of idlers to run.// Idle handles only run if the queue is empty or if the first message// in the queue (possibly a barrier) is due to be handled in the future.//找了一圈发现没有要处理的消息了那么就开始判断是否有IdleHandler的消息要处理//注意这里的pendingIdleHandlerCount第一次进入才是-1后续一旦执行IdleHandler都是变成0不会再进入if (pendingIdleHandlerCount 0 (mMessages null || now mMessages.when)) {//把mIdleHandlers集合大小赋值给pendingIdleHandlerCountpendingIdleHandlerCount mIdleHandlers.size();}//如果发现没有IdleHandler那么就返回循环进行block阻塞等待唤醒if (pendingIdleHandlerCount 0) {// No idle handlers to run. Loop and wait some more.mBlocked true;continue;}//如果mPendingIdleHandlers这个数组没有初始化就进行初始化这里最小大小为4应该是为了性能以防频繁扩容if (mPendingIdleHandlers null) {mPendingIdleHandlers new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];}//mIdleHandlers转成了数组mPendingIdleHandlersmPendingIdleHandlers mIdleHandlers.toArray(mPendingIdleHandlers);}// Run the idle handlers.// We only ever reach this code block during the first iteration.//开始正式执行对应的IdleHandlerfor (int i 0; i pendingIdleHandlerCount; i) {final IdleHandler idler mPendingIdleHandlers[i];mPendingIdleHandlers[i] null; // release the reference to the handlerboolean keep false;try {//执行IdleHandler的对应回调业务方法keep idler.queueIdle();} catch (Throwable t) {Log.wtf(TAG, IdleHandler threw exception, t);}//这里的keep就是queueIdle的返回值如果返回false就会从mIdleHandlers进行移除if (!keep) {synchronized (this) {mIdleHandlers.remove(idler);}}}//把pendingIdleHandlerCount变成0不是-1这样防止死循环执行IdleHandler// Reset the idle handler count to 0 so we do not run them again.pendingIdleHandlerCount 0;//这里是为了让尽快遍历一下是否有消息因为可能执行IdleHandler期间有新消息// While calling an idle handler, a new message could have been delivered// so go back and look again for a pending message without waiting.nextPollTimeoutMillis 0;}}上面next方法关于IdleHandler执行总结如下 1、next方法遍历消息队列确实没有寻找到要处理的消息任务 2、没有要处理的消息则开始处理IdleHandler相关的任务 3、如果IdleHandler的queueIdle返回false则会从mIdleHandlers删除下次空闲就不会在执行这个IdleHandler否则true的话会每次空闲都执行 实战案例 测试一下queueIdle返回false,即只执行一次queueIdle protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);getMainLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {Overridepublic boolean queueIdle() {//TODO 执行一些不那么紧急任务 Trace.beginSection(queueIdle no next runing);Log.i(lsm66666,queueIdle return false,no next runing);Trace.endSection();return false;}});}验证结果
再测试一下queueIdle返回true,即执行多次queueIdle protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);getMainLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {Overridepublic boolean queueIdle() {//TODO 执行一些不那么紧急任务 Trace.beginSection(queueIdle has next runing);Log.i(lsm66666,queueIdle return true,has next runing);Trace.endSection();return true;}});}看看日志打印情况
systrace结合分析IdleHandler 上面也可以看出来IdleHandler的执行都在没有消息可以处理了才会执行而且执行完成后就进入消息等待时期。 从上面也可以看出来IdleHandler确实是在主线程空闲暂时没有消息处理时候进行执行的可以起到一个错峰执行的目的不过也要注意以下几点 1、切勿让IdleHandler执行耗时操作应该是可以快速完成的一些任务 2、尽量都让IdleHandler执行是一次性任务即queueIdle返回false以防每次空闲都有重复调用 文章参考https://mp.weixin.qq.com/s/7R2ws-6oBij3OrNMA_IfTA 更多framework实战开发干货请关注下面“千里马学框架”