Handler.removeclass不起作用Messages的作用,有时候为什么一定要先removeclass不起作用一下

14802人阅读
android(59)
mHandler.removeCallbacks(mRunnable);
handler.removeMessages(what);
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:350136次
积分:3792
积分:3792
排名:第8276名
原创:78篇
转载:16篇
评论:36条
(3)(1)(2)(2)(1)(2)(4)(2)(21)(55)(1)Handler.removeCallbacks(Runnable r)失效原因 - 简书
Handler.removeCallbacks(Runnable r)失效原因
今天发现一个问题就是Android中使用Handle的removeCallbacks函数将Runnable移除,可是有时候会失效,在网上搜索了很久,大部分都是解决方法,依然没有说明为什么失效的原因。
在StackOverFlow找到一点原因:
It appears to me that removeCallbacks(..) only stops pending messages (Runnables). If your runnable has already started, then there's no stopping it (at least not this way).
removeCallbacks只能停止处于即将运行状态的messages,这里messages里面包含就是Runnables,如果Runnbale已经启动start(),则removeCallbacks是无法停止的。
感觉很厉害的人都是自己找问题答案的,所以今天我也要学学他们,自己找答案。
在Handler的removeCallbacks()方法是调用:
public final void removeCallbacks(Runnable r)
mQueue.removeMessages(this, r, null);
mQueue就是MessageQueue,接着看removeMessages方法
void removeMessages(Handler h, Runnable r, Object object) {
if (h == null || r == null) {
synchronized (this) {
Message p = mM
// Remove all messages at front.
// 就是将当前处于mMessage前面的message(里面有目标callback)移除
while (p != null && p.target == h && p.callback == r
&& (object == null || p.obj == object)) {
Message n = p.
mMessages =
p.recycleUnchecked();//将移除的message放入pool中
// Remove all messages after front.
// 就是将当前处于后面的message(里面有目标callback)移除
while (p != null) {
Message n = p.
if (n != null) {
if (n.target == h && n.callback == r
&& (object == null || n.obj == object)){
Message nn = n.
n.recycleUnchecked();
可见mQueue.removeMessages(this, r, null);是将messageQueue中的包含有我们想要移除的callback的message全部移除掉,这样不就达到阻止runnable运行的目的了吗?
但是假如我们想要移除的callback不在messageQueue中,那么mQueue.removeMessages也就失效了。
因为已经处于运行的runnable包含在message中已经移交给handler进行处理了,而Handler.removeCallbacks(Runnable r)只能移除未运行的runnable,所以导致无法停止runnbale的运行,最后失效。
努力学习的学生狗Android学习笔记(3)
4.Handler移除消息
handler不只能发送一个消息,而且还能移除消息。当我们调用handler.post()方法时,调用handler.removeCallbacks(myRunnable)方法,可以移除正在调用的对象。当调用handler.sendMessage()方法时,可以通过调用
handler.removeMessages(int )方法移除正在调用的对象;
实例五:拦截消息
布局代码:
&RelativeLayout xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"&
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:text="hello" /&
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:text="发送消息" /&
android:id="@+id/intercept"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/send"
android:layout_below="@+id/send"
android:layout_marginTop="40dp"
android:text="拦截消息" /&
&/RelativeLayout&
java逻辑代码:
public class MainActivity extends Activity implements OnClickListener{
private Button intercept,
private TextV
Handler handler = new Handler(){
public void handleMessage(Message msg) {
if (msg.what ==1) {
tv.setText(msg.obj+"");
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intercept = (Button)findViewById(R.id.intercept);
send = (Button)findViewById(R.id.send);
send.setOnClickListener(this);
intercept.setOnClickListener(this);
tv = (TextView)findViewById(R.id.textView1);
public void onClick(View v) {
switch (v.getId()) {
case R.id.send:
new Thread(){
public void run() {
Message msg = handler.obtainMessage();
msg.what = 1;
msg.obj = "你拦截不到,哈哈哈";
handler.sendMessageDelayed(msg, 5000);
}.start();
case R.id.intercept:
handler.removeMessages(1);
5.Handler移除消息内容
上述的例子展示的是handler如何移除一条消息的对象,除此之外我们也可以拦截消息内容。
实例六:拦截消息内容
布局代码:
xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"&
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="send"
android:text="发送消息" /&
java逻辑代码:
public class MainActivity extends Activity {
Handler handler = new Handler(new Handler.Callback() {
public boolean handleMessage(Message msg) {
Log.i("tag", "handle--1:"+msg.arg1);
if (msg.what&100) {
return false;
return true;
public void handleMessage(Message msg) {
Log.i("tag", "handle--2:"+msg.arg1);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
public void send(View view){
new Thread(){
public void run() {
Message message = Message.obtain();
message.arg1 = 98;
handler.sendMessage(message);
}.start();
初始化handler的对象时,传入callback参数,重写callback中的handlemessage的方法,如果返回值设置为false不拦截消息,如果返回值设置为true,则拦截。
6.Handler的原理是什么?
Handler封装了消息的发送,主要包括消息发送给谁
Looper类主要用于一个线程循环获取消息队列中的消息。
Looper的作用主要是负责管理消息队列,负责消息的出列和入列操作。
MessageQueue:就是一个消息队列,可以添加消息,并处理消息。
Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。
Handler 负责发送消息,looper负责接收handler发送的消息,并直接把消息传递给handler自己,MessageQueue就是一个存储消息的容器。
Looper的知识:
1.每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal
2.Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行
3.Looper使一个线程变成Looper线程。
如何实现一个与线程相关的handler
所谓的消息机制其实很简单,实现这种机制需要只需要五步:
1、调用Looper.prepare(),线程变成循环线程;
2、实例化Handler,这里需要覆盖handleMessage方法,处理收到的消息;
3、 调用Looper.loop();使线程进入循环;
4、 实例化Message对象,调用已经实例化好的handler对象的obtainMessage方法,把数据传给obtainMessage方法,obtainMessage方法就会实例化一个Message对象。(这里也可以发送实现Runnable接口的对象);
5、调用Handler的sendMessage方法把实例化好的Message对象发送出去。
实例七:如何实现一个handler与自定义线程相关联
逻辑代码:
public class MainActivity extends Activity {
Handler handler = new Handler(){
public void handleMessage(Message msg) {
Log.i("tag", "Thread:"+Thread.currentThread().getName());
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
thread = new MyThread();
thread.start();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
thread.handler.sendEmptyMessage(1);
handler.sendEmptyMessage(1);
class MyThread extends Thread{
public void run() {
super.run();
Looper.prepare();
handler = new Handler(){
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("tag", "Thread:"+Thread.currentThread().getName());
Looper.loop();
初学者在学习handler消息机制时,往往会产生一个误区,认为只有主线程才有handler,才能够实现通信,通过上面的例子,我们可以看出在子线程中同样也有handler,但是需要实现线程添加looper,才能够得到该线程中的handler。
Android中更新ui的几种方式。
handler post( );
handler sendMessage( );
view post( );
runOnUiThread( );
包含以上四种方式,前两种与handler相关。第三种一般在主线程中调用,避免因为线程嵌套出现线程错乱的现象,第四种会回到主线程中执行。
实例八:Android中更新ui的方式
逻辑代码:
public class MainActivity extends Activity {
private TextV
Handler handler = new Handler(){
public void handleMessage(Message msg) {
tv.setText("handler sendmessage update ui");
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.tv);
viewPost();
* 通过handler的sendMessage发送数据,更新ui
public void handlerSendMessage(){
handler.sendEmptyMessage(1);
* 通过handler的post方法,更新ui
public void handlerPost(){
handler.post(new Runnable() {
public void run() {
tv.setText("handler post update ui");
* runOnUiThreadUpdateUi回到主线程,更新ui
public void runOnUiThreadUpdateUi(){
runOnUiThread(new Runnable() {
public void run() {
tv.setText("runOnUiThread update ui");
* view的post方法,更新ui
public void viewPost(){
tv.post(new Runnable() {
public void run() {
tv.setText("view post update ui");
以上为handler的使用方法和消息处理机制的原理,更多相关代码资源请下载:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1323次
排名:千里之外}

我要回帖

更多关于 removeattr 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信