导航:首页 > 操作系统 > androidhandler关闭

androidhandler关闭

发布时间:2022-09-06 14:44:55

android Handler那些事儿,消息屏障IdelHandlerANR

Handler 是Android SDK中用来处理异步消息的核心类,子线程可以通过handler来通知主线程进行ui更新。

备注:本文源码截图 基于Android sdk 28

Handler机制 消息发送主要流程如图

应用程序启动后,zygote fork一个应用进程后,和普通java程序一样,程序会首先执行ActivityThread中的main函数。在main函数中,程序首先会创建Looper对象并绑定到主线程中,然后开启loop循环。(ps:主线程loop循环不能退出)

在prepareMainLooper方法中,最终会创建Looper,MessageQueue对象 以及创建native层MessageQueue对象。

使用Handler.sendMessageXXX或这 postDedayXXX发送消息后,最终会调用到SendMessageAtTime方法中。

然后调用MessageQueue.enqueueMessage将消息存到消息队列中。

存入消息后,然后通过调用native方法 唤醒主线程进行消息处理。

当应用程序启动,做完一些必要工作之后,便会开启Loop循环,除非系统异常,否则该循环不会停止。loop循环中,主要做两件事,第一,从消息队列中取消息。第二,进行消息分发处理。

MessageQueue.next() 方法 通过调用 native方法 nativePollOnce(ptr, nextPollTimeoutMillis)实现无消息处理时,进入阻塞的功能。
当nextPollTimeoutMillis 值为0时,该方法会立刻返回;
当nextPollTimeoutMillis 值为-1时,该方法会无限阻塞,直到被唤醒;
当nextPollTimeoutMillis 值大于0时,该方法会将该值设置为超时时间,阻塞到达一定时间后,返回;

在loop循环中 ,通过调用 msg.target.dispatchMessage(msg) 进行消息的分发处理

使用当前线程的MessageQueue.addIdleHandler方法可以在消息队列中添加一个IdelHandler。

当MessageQueue 阻塞时,即当前线程空闲时,会回调IdleHandler中的方法;

当IdelHandler接口返回false时,表示该IdelHandler只执行一次,

a,延迟执行

例如,当启动Activity时,需要延时执行一些操作,以免启动过慢,我们常常使用以下方式延迟执行任务,但是在延迟时间上却不好控制。

其实,这时候使用IdelHandler 会更优雅

b,批量任务,任务密集,且只关注最终结果

例如,在开发一个IM类型的界面时,通常情况下,每次收到一个IM消息时,都会刷新一次界面,但是当短时间内, 收到多条消息时,就会刷新多次界面,容易造成卡顿,影响性能,此时就可以使用一个工作线程监听IM消息,在通过添加IdelHandler的方式通知界面刷新,避免短时间内多次刷新界面情况的发生。

在Android的消息机制中,其实有三种消息: 普通消息、异步消息及消息屏障。

消息屏障 也是一种消息,但是它的target为 null。可以通过MessageQueue中的postSyncBarrier方法发送一个消息屏障(该方法为私有,需要反射调用)。

在消息循环中,如果第一条消息就是屏障消息,就往后遍历,看看有没有异步消息:
如果没有,则无限休眠,等待被唤醒
如果有,就看离这个消息被触发时间还有多久,设置一个超时时间,继续休眠

异步消息 和普通消息一样,只不过它被设置setAsynchronous 为true。有了这个标志位,消息机制会对它有些特别的处理,我们稍后说。

所以 消息屏障和异步消息的作用 很明显,在设置消息屏障后,异步消息具有优先处理的权利。

这时候我们回顾将消息添加到消息队列中时,可以发现,其实并不是每一次添加消息时,都会唤醒线程。
当该消息插入到队列头时,会唤醒该线程;
当该消息没有插入到队列头,但队列头是屏障,且该消息是队列中 靠前的一个异步消息,则会唤醒线程,执行该消息;

调用MessageQueue.removeSyncBarrier 方法可以移除指定的消息屏障

ANR 即 Application Not Response, 是系统进程对应用行为的一种监控,如果应用程序没有在规定时间内完成任务的话,就会引起ANR。

ANR类型

Service Timeout : 前台服务20s, 后台服务200s

BroadcastQueue Timeout : 前台广播 10s,后台广播60s

ContentPrivider Timeout : 10s

InputDispatching Timeout : 5s

比如,在启动一个服务时, AMS端通过应用进程的Binder对象创建Service, 在scheleCreateService()方法中 会调用到当前service的onCreate()生命周期函数;

bumpServiceExecutingLocked()方法内部实际上会调用到scheleServiceTimeoutLocked()方法,发送一个ActivityManagerService.SERVICE_TIMEOUT_MSG类型消息到AMS工作线程中。

消息的延时时间,如果是前台服务,延时20s, 如果是后台服务,延时200s;

如果Service的创建 工作在 上诉消息的延时时间内完成,则会移除该消息,

否则,在Handler正常收到这个消息后,就会进行服务超时处理,即弹出ANR对话框。

复杂情况下,可能会频繁调用sendMessage 往消息队列中,添加消息,导致消息积压,造成卡顿,

1,重复消息过滤

频繁发送同类型消息时,有可能队列中之前的消息还没有处理,又发了一条相同类型的消息,更新之前的数据,这时候,可以采用移除前一个消息的方法,优化消息队列。

2,互斥消息取消

在发送消息时,优先将消息队列中还未处理的信息已经过时的消息 移除,优化队列

3,队列优化-复用消息

创建消息时,优先采用之前回收的消息,避免重复创建对象,引起GC

完~
(如果错误或不足,望指出, 大家共同进步)

Ⅱ 如何关闭android中的HandlerThread

android 中的HandlerThread包含了android中的消息处理机制必须的looper,当你启动这个线程的时候,就会闯进looper,并开启消息处理的循环。
跟其它线程一样,HandlerThread是可不可以直接stop掉的,不过经过本人测试,你可以调用:getLooper().quit();来退出这个线程,其实原理很简单,就是改变在消息循环里面标志位,退出整个while循环,使线程执行完毕。
部分 测试代码如下:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv_name = (TextView) findViewById(R.id.tv_name);
btn_name = (Button) findViewById(R.id.btn_name);
Log.i(TAG, "==================main thread:" + Thread.currentThread().getName());
final HandlerThread thread = new HandlerThread("handlerThread");
thread.start();
final MyHandler handler = new MyHandler(thread.getLooper());
btn_name.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {
handler.sendEmptyMessage(1);try {Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();}thread.getLooper().quit();}});}
class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);}@Overridepublic void handleMessage(Message msg) {
Log.i(TAG, "==================" + Thread.currentThread().getName());
//tv_name.setText("hello, this is the first message from handler");
不过要注意:要想更新界面内容,还是需要使用界面的Looper,不然的话还是会抛错误,还是那句话,所有跟改变界关的操作,都得通过界面的Looper来执行

Ⅲ android handler是不是唯一的

前段时间在工作的时候碰见一个问题,就是要待机时在设定的时间内执行操作,开始并没有意识到问题的严重,后来尝试很多办法没有成功,最后也是在网上找到解决办法,在此稍作总结,希望能对大家有所帮助,不足之处还望大家指正。
1Android中的handler、timer、thread、在待机时都会停止运行,所设定的时间会在待机结束后继续计算。所以如果想在Android待机时运行某些操作,使用以上几种方法是不可行的。
2Android中有一个Alarmmanager对象,可以使用该对象执行待机时的操作。具体设置的方法如下:
2.1设置闹铃的类型
AlarmManager.RTC,硬件闹钟,不唤醒手机(也可能是其它设备)休眠;当手机休眠时不发射闹钟。
AlarmManager.RTC_WAKEUP,硬件闹钟,当闹钟发躰时唤醒手机休眠;
AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒手机休眠;当手机休眠时不发射闹钟。
AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,当闹钟发躰时唤醒手机休眠;
AlarmManager.POWER_OFF_WAKEUP:能唤醒系统,他是一种关机闹铃,就是说设备在关机状态下也可以唤醒系统,所以我们把它称为关机闹铃。
RTC闹钟和ELAPSED_REALTIME最大的差别就是前者可以通过修改手机时间触发闹钟事件,后者要通过真实时间的流逝,即使在休眠状态,时间也会被计算。
2.2设置闹铃的开始时间
如果使用ELAPSED_REALTIME或者ELAPSED_REALTIME_WAKEUP类型应该调用SystemClock.elapsedRealtime()获取相对时间在加上你设定的延迟时间
如果使用RTC或者RTC_WAKEUP类型应该调用System.currentTimeMillis()获取从1970.1.1号以来的时间在加上你设定的延迟时间
2.3pendingintent
一个PendingIntent对象,表示到时间后要执行的操作。PendingIntent与Intent类似,可以封装Activity、BroadcastReceiver和Service。
但与Intent不同的是,PendingIntent可以脱离应用程序而存在。

接触Android没几天,不太了解。
本来写好的一个应用在无意中发现,待机的时候,应用中的一个线程停止了运行。
这个线程是每隔一分钟上传一个数据到服务器上。
我当时测试的时候,没想过待机(接开关键)下的情况是怎样的,现在发现,只要手机一进入待机状态,这个线程就停止工作了。
不过有一个奇怪的现象,因为我的应用中同时启动了三个线程。
一个负责每隔一分钟上传一个数据,当待机的时候,这个线程暂停运行,当手机不待机的时候,马上复活。
一个负责接收服务器发过来的UDP数据包,这个线程倒是不受待机的影响,当有数据来的时候,可以正常处理。
难道是因为datagramSocket.receive(datagramPacket);阻塞的原因?
public void run()
{
while(true)
{
datagramSocket.receive(datagramPacket); //阻塞
}
}

到网上搜索了一下,看到别人说的:
实验1:使用Java.util.Timer
当连接USB线进行调试时,会发现一切工作正常,每5秒更新一次界面,即使是按下电源键,仍然会5秒触发一次。
当拔掉USB线,按下电源键关闭屏幕后,过一段时间再打开,发现定时器明显没有继续计数,停留在了关闭电源键时的数字。

实验2:使用AlarmService:
2.1通过AlarmService每个5秒发送一个广播,setRepeating时的类型为AlarmManager.ELAPSED_REALTIME。
拔掉USB线,按下电源键,过一段时间再次打开屏幕,发现定时器没有继续计数。
2.2setRepeating是的类型设置为AlarmManager.ELAPSED_REALTIME_WAKEUP
拔掉USB线,按下电源键,过一点时间再次打开屏幕,发现定时器一直在计数。

如此看来,使用WAKEUP才能保证自己想要的定时器一直工作,但是肯定会引起耗电量的增加。

我最后自已写了一个Service类,然后使用AlarmService每隔一分钟执行一次,在待机的时候也能正常运行。

Ⅳ 如何终止Android Handler 中的消息处理

终止Android Handler 中的消息处理的办法:

  1. 首先你可以放到线程中去执行,这个应该是个耗时操作,放到UI线程中,程序会假死。

  2. 然后你可以通过handler去启动这个线程来执行这个方法,如果取消的话,在发给handler一个消息,让handler再去停止这个线程。

Ⅳ Android的handler机制的原理

Android的handler机制的原理分为异步通信准备,消息发送,消息循环,消息处理。

1、异步通信准备

在主线程中创建处理器对象(Looper)、消息队列对象(Message Queue)和Handler对象。

2、消息入队

工作线程通过Handler发送消息(Message) 到消息队列(Message Queue)中。

3、消息循环

消息出队: Looper循环取出消息队列(Message Queue) 中的的消息(Message)。

消息分发: Looper将取出的消息 (Message) 发送给创建该消息的处理者(Handler)。

4、消息处理

处理者(Handler) 接收处理器(Looper) 发送过来的消息(Message),根据消息(Message) 进行U操作。

handler的作用

handler是android线程之间的消息机制,主要的作用是将一个任务切换到指定的线程中去执行,(准确的说是切换到构成handler的looper所在的线程中去出处理)android系统中的一个例子就是主线程中的所有操作都是通过主线程中的handler去处理的。

Handler的运行需要底层的 messagequeue和 looper做支撑。



Ⅵ android 关于Handler终止问题

你的判断语句有问题,相当于移除了消息又添加了消息,加一个else应该就能解决。

if(progress>=stop){
mHandler.removeMessages(MSG_PROGRESS_UPDATE);
}else{
mHandler.sendEmptyMessageDelayed(MSG_PROGRESS_UPDATE,30);
}

Ⅶ android应用关闭了 销毁了 但是fragment里边的handler还在运行 怎么回事

1、不要直接将Fragement写在XML文件里,这样会导致Fragment对象无法销毁,产生内存溢出。在代码动态的new 和add Fragement才是正确的做法。 2、使用抽屉方法,在XML文件里放两个LinearLayout,然后在代码中将Fragment加进这两个LinearLayout中

Ⅷ 安卓定时器Handler如何关闭

{
publicTimeCounts(longmillisInFuture,longcountDownInterval){
super(millisInFuture,countDownInterval);//参数依次为总时长,和计时的时间间隔
}

@Override
publicvoidonFinish(){//计时完毕时触发

}

@Override
publicvoidonTick(longmillisUntilFinished){//计时过程显示
//倒计时数可以写在这儿
}
}

TimeCounts timeCounts = new TimeCounts(30000, 1000);//总时长30s,间隔1s

timeCounts.start();//倒计时开始

timeCounts.cancel();//取消倒计时

Ⅸ android中,怎么停止handler

Android四大组件如人体四肢,Handle如人体中的血液。它贯穿于各个组件,连Activity的onCreat方法都是由它调用的。你让它停下来?我真的很好奇: 你的程序怎么跑???

阅读全文

与androidhandler关闭相关的资料

热点内容
橙app如何开启聊天 浏览:897
访问服务器公网地址 浏览:664
pdf打印底色去掉 浏览:463
java快递接口 浏览:397
哪个app可以教新爸爸 浏览:210
如何查看服务器系统版本信息 浏览:524
成都市土地出让金算法 浏览:702
钢筋加密标记 浏览:576
ps中扩展功能在文件夹的什么位置 浏览:904
双极压缩机为什么要先高压 浏览:527
苹果手机服务器填什么 浏览:832
android移动动画效果 浏览:691
电子和服务器是什么意思 浏览:691
phpurl中文乱码问题 浏览:893
程序员那么可爱大结局陆漓产子 浏览:538
java如何从云服务器读取本地文件 浏览:924
压缩空气软管制作方法 浏览:912
天河三号算法 浏览:925
php队列教程 浏览:633
洪水命令 浏览:531