android启动慢怎么解决(Android延迟执行),本文通过数据整理汇集了android启动慢怎么解决(Android延迟执行)相关信息,下面一起看看。
首先,需要明确一点,处理程序延时消息机制不是延时发送消息,而是延时去处理消息;举个例子,如下:
处理程序。发布延迟(()-{ log。e(\\\ " zjt \\\ ",\ \ \ "延迟可运行\ \ \ ");}, 3_000);
上面的处理者不是延时3秒后再发送消息,而是将消息插入消息队列后等3秒后再去处理。
延迟的的方法如下:
public final布尔post delayed(@ NonNull Runnable r,long delay millis){ return sendmessage delayed(getPostMessage(r),delay millis);}
其中的getPostMessage就是将邮政的可追捕的包装成消息,如下:
私有静态消息getPostMessage(Runnable r) { //使用Message.obtain()避免重复创建实例对象,达到节约内存的目的消息m=消息。获取();m . callback=r;返回m;}
sendMessageDelayed延迟延迟方法如下:
public final布尔sendmessage delayed(@ NonNull Message msg,long delay millis){ if(delay millis 0){ delay millis=0;} //延时的时间是手机的开机时间(不包括手机休眠时间)需要延时的时间返回sendMessageAtTime(msg,系统时钟。正常运行时间毫秒()延迟毫秒);}
sendMessageAtTime如下:
public boolean sendmessage time(@ NonNull Message msg,long uptime millis){ Message queue queue=m queue;if(queue==null){运行时异常e=新的运行时异常(this \ \ \ " sendmessage attime()调用时未使用mQueue \ \ \ ");Log.w(\\\"Looper\\\ ",e.getMessage(),e);返回false}返回enqueueMessage(队列、消息、正常运行时间毫秒);}
这里面的代码很好理解,就不说了,看看入队消息:
私有布尔入队消息(@非空消息队列queue,@非空消息消息,长正常运行时间毫秒){ msg。目标=这个;//设置味精的目标为处理程序消息。worksource uid=threadlocalworksource。getuid();//异步消息,这个需要配合同步屏障来使用,可以看我之前的文章,这里不赘述if(mAsynchronous){ msg。设置异步(真);} //插入到消息队列中返回queue.enqueueMessage(msg,正常运行时间毫秒);}
消息队列的入队消息的方法如下:
布尔入队消息(消息,长时){ if(消息。target==null){ throw new IllegalArgumentException(\ \ \ "消息必须有目标。\\\");} if(msg。is inuse()){ throw new IllegalStateException(msg \ \ \ "此消息已在使用中。\\\");}同步(这个){ //判断发送消息的进程是否还活着if(MQ iting){ IllegalStateException e=new IllegalStateException(msg。目标\ \ \ "向死线程上的处理程序发送消息\ \ \ ");Log.w(TAG,e.getMessage(),e);味精。recycle();//回收消息到消息池返回false} msg。markin use();//标记消息正在使用当=当消息p=消息;//获取表头消息布尔needWake//如果队列中没有消息或者消息为即时消息或者表头消息时间大于当前消息的延时时间if(p==null
when==0
when p . when){//新头,如果阻塞则唤醒事件队列味精。next=p;mMessages=msg .//表示要唤醒支持器对应的线程,这个后面解释need wake=m blocked } else { need wake=m blocked p . target==null msg。isa synchronous();消息上一页//如下都是单链表尾插法,很简单,不赘述for(;){ prev=p;p=p . nextif(p==null
when p . when){ break;} if(need wake p . isa synchronous()){ need wake=false;} }味精。next=p;//不变量:p==prev。下一页。next=msg} //唤醒处理者对应的线程if(需要唤醒){原生唤醒(mPtr);} }返回真实}
举个例子,假设我们消息队列是空的,然后我发送一个延时10s的延时消息,那么会直接把消息存入消息队列。
从消息队列中获取消息是通过Looper.loop()来调用消息队列的下一个()方法,下一个()的主要代码如下:
Message next() { //如果消息循环已经退出并被释放,则返回此处。//如果应用程序在不支持的情况下退出//后试图重新启动looper,就会发生这种情况。最终长ptr=mPtrif (ptr==0) {返回null } int pendingIdleHandlerCount=-1;//-1仅在第一次迭代期间int nextPollTimeoutMillis=0;for(;){ if (nextPollTimeoutMillis!=0){ binder。flushpendingcommands();} //表示要休眠多长时间,功能类似于等待时间//-1表示一直休眠, //等于0时,不堵塞//当有新的消息来时,如果处理者对应的线程是阻塞的,那么会唤醒nativePollOnce(ptr,nextPollTimeoutMillis);同步(this) { //尝试检索下一条消息。找到就还最终long now=系统时钟。正常运行时间millis();message prev msg=null message msg=m messages如果(味精!=null msg.target==null) { //被障碍物阻挡。查找队列中的下一条异步消息do { prevMsg=msgmsg=msg.next}而(味精!=null!味精。isasynchronous());}如果(味精!=null) { if (now msg.when) { //计算延时消息的剩余时间nextPollTimeoutMillis=(int)math。最小(消息。当——现在,整数MAX _ VALUE);} else { //收到消息mBlocked=falseif (prevMsg!=null){上一条消息。下一个=msg。接下来;} else { mMessages=msg . next } msg . next=nullif(调试)Log.v(标记,\ "返回消息:\ \ \ " msg);味精。markin use();返回msg} } else { //不再有消息nextPollTimeoutMillis=-1;}
…….//判断是否有闲置的任务,即主线程空闲时需要执行的任务,这个下面说
if(pendingIdleHandlerCount=0){//这里表示所有到时间的消息都执行完了,剩下的如果有消息一定是延时且时间还没到的消息;//刚上面的入队消息就是根据这个变量来判断是否要唤醒处理者对应的线程mBlocked=true继续;}
…… } }
其实,从这里就可以看出来,处理程序的延时消息是如何实现的了。
比方说发送一个延时10s的消息,那么在下一个()方法是,会阻塞(10s发送消息时的系统开机时间 执行下一个()方法是系统的开机时间),到达阻塞时间时会唤醒。或者这时候有新的消息来了也会根据mBlocked=true来唤醒。
IdleHandler是什么?
在消息队列类中有一个静电的接口IdleHanlder:
公共静态接口空闲处理程序{布尔队列idle();}
当消息队列中无可处理的消息时回调;作用:用户界面线程处理完所有事务后,回调一些额外的操作,且不会堵塞主进程;
接口中只有一个队列空闲()函数,线程进入堵塞时执行的额外操作可以写这里,返回值是真实的的话,执行完此方法后还会保留这个IdleHandler否则删除。
更多android启动慢怎么解决(Android延迟执行)相关信息请关注本站,本文仅仅做为展示!