精华内容
下载资源
问答
  • Android Handler机制

    2019-01-16 20:43:57
  • 安卓Handler机制

    千次阅读 2019-03-16 14:57:17
    Handler机制运用在安卓线程之间的消息传递。Handler之所以能够运行,得力于与Handler紧密相联的Looper,每一个线程都只能有一个Looper,一个Looper就可以看成一个事件执行者,Handler决定对事件做什么具体操作,所以...

    Handler机制运用在安卓线程之间的消息传递。Handler之所以能够运行,得力于与Handler紧密相联的Looper,每一个线程都只能有一个Looper,一个Looper就可以看成一个事件执行者,Handler决定对事件做什么具体操作,所以一般继承了Handler就要重写其中的handleMessage方法,那么事件从哪里来呢?从消息队列MessageQueue中得来。
    Handler的使用方法:

    protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		//创建handler对象
    		handler = new Handler() {
    		//重载handler的handlemessage方法
    			@Override
    			public void handleMessage(Message msg) {
    				Log.i("TAG", "处理了事件");
    				super.handleMessage(msg);
    			}
    		};
    
    		Thread t1 = new Thread() {
    			@Override
    			public void run() {
    			//新开一个线程,向主线程发送消息
    				Message obtain = Message.obtain();
    				handler.sendMessage(obtain);
    				super.run();
    			}
    		};
    		t1.start();
    	}
    

    程序执行起来之后,就会打印“处理了事件”

    让我们一探其中的原理:
    从上面的代码来看,没看到什么Looper和MessageQueue,只看到了new一个Handler和handler发送了一个消息.
    让我们看一看new一个Handler时,系统为我们做了什么,首先看Handler的一个构造函数:

    public Handler(Callback callback, boolean async) {
            if (FIND_POTENTIAL_LEAKS) {
                final Class<? extends Handler> klass = getClass();
                if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                        (klass.getModifiers() & Modifier.STATIC) == 0) {
                    Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                        klass.getCanonicalName());
                }
            }
    		//获取当前线程的Looper,如果Looper为null,那么抛出异常
            mLooper = Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                    "Can't create handler inside thread that has not called Looper.prepare()");
            }
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    

    上面的代码有一句判断当前线程的Looper有没有创建出来,如果没有,就直接报错。好像上面的例子中,我们并没有创建Looper啊,为什么我们的例子没有报异常。其实上面的例子是在主线程中创建的Handler的,在创建主线程的时候,系统已经默认为我们创建Looper了,因此不会报异常,但在其他线程中就要先创建Looper了,具体例子下面有。

    有了Looper之后,MessageQueue也就有了,是在Looper的构造函数里面绑定了一个MessageQueue,先假设都有了,先看handler.sendMessage(obtain)里面干了什么,这里面其实是向MessageQueue插入了一条消息,最后调用到了MessageQueue的enqueueMessage方法

    final boolean enqueueMessage(Message msg, long when) {
            if (msg.isInUse()) {
                throw new AndroidRuntimeException(msg + " This message is already in use.");
            }
            if (msg.target == null) {
                throw new AndroidRuntimeException("Message must have a target.");
            }
    
            boolean needWake;
            synchronized (this) {
                if (mQuiting) {
                    RuntimeException e = new RuntimeException(
                            msg.target + " sending message to a Handler on a dead thread");
                    Log.w("MessageQueue", e.getMessage(), e);
                    return false;
                }
    
                msg.when = when;
                Message p = mMessages;
                if (p == null || when == 0 || when < p.when) {
                    // New head, wake up the event queue if blocked.
                    msg.next = p;
                    mMessages = msg;
                    needWake = mBlocked;
                } else {
                    // Inserted within the middle of the queue.  Usually we don't have to wake
                    // up the event queue unless there is a barrier at the head of the queue
                    // and the message is the earliest asynchronous message in the queue.
                    needWake = mBlocked && p.target == null && msg.isAsynchronous();
                    Message prev;
                    for (;;) {
                        prev = p;
                        p = p.next;
                        if (p == null || when < p.when) {
                            break;
                        }
                        if (needWake && p.isAsynchronous()) {
                            needWake = false;
                        }
                    }
                    msg.next = p; // invariant: p == prev.next
                    prev.next = msg;
                }
            }
            if (needWake) {
                nativeWake(mPtr);
            }
            return true;
        }
    

    如果needWake为true,就会唤醒与之相关联的Looper,Looper会在loop方法中调用MessageQueue的next方法,next方法会堵塞,正好在这个enqueueMessage方法中唤醒,唤醒之后Looper又可以接着处理消息了.

    下面来看一下在非主线程中创建Handler的例子:

    Thread thread = new Thread() {
    			public void run() {
    			//在非主线程中使用handler要首先创建Looper
    				Looper looper = Looper.myLooper();
    				//将Looper作为线程私有数据保存起来
    				looper.prepare();
    				final Handler handler = new Handler() {
    					@Override
    					public void handleMessage(Message msg) {
    						String TAG = "abc";
    						Log.i(TAG, "handle message");
    						super.handleMessage(msg);
    					}
    				};
    			//新建一个线程,用来发送Message
    				Thread thread = new Thread() {
    					public void run() {
    						Message obtain = Message.obtain();
    						handler.sendMessage(obtain);
    					};
    
    				};
    				thread.start();
    				//最后一定要调用此方法,looper才算真正运行起来了,因为这个方法是无限循环,后面的方法可能不会得到执行,除非其他地方调用了quit方法
    				looper.loop();
    
    			};
    
    		};
    		thread.start();
    
    展开全文
  • 安卓handler机制

    2020-11-27 18:25:21
    安卓在设计时就封装了一套消息创建,传递,处理机制,如果不遵循这样的机制,就无法更新ui信息,并抛出异常: 不能在非UI线程中去更新UI。 因此就引入了hanlder机制 特点 a. 允许你去发送并处理一条runnable对象和...

    Handler

    Android中 ui的更新需要在主线程中进行,一些耗时的操作我们会放在后台线程中进行,而将执行结果在ui线程中进行。 安卓在设计时就封装了一套消息创建,传递,处理机制,如果不遵循这样的机制,就无法更新ui信息,并抛出异常: 不能在非UI线程中去更新UI。 因此就引入了hanlder机制

    特点
    a. 允许你去发送并处理一条runnable对象和messageQueue相关联的信息。
    b. 每一个handler的实例都与一个单独的线程
    c. 当创建一个新的处理程序时,它将绑定到正在创建线程的线程/消息队列, 从那个点开始,它将向该消息队列传递信息和runnables,并在它们从消息队列中释放和执行它们。

    运行机制

    转自:https://blog.csdn.net/ttxs99989/article/details/81814037?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control

    Handler机制也可以叫做异步机制, 它由四个部分组成分别是: Message. Handler, MessageQueue, Looper

    1. Message
    Message是在线程中传递的消息,它可以在内部携带少量的消息, 用于在不同线程中交换数据, Message的arg1, arg2可以储存int数据, obj可以携带object数据。

    2. Handler
    Handler 就是处理者的意思。 它只要用于在子线程发送传送消息对象Message, 在UI对象处理消息对象Message, 在子线程调用sendMessege方法发送消息对象Message, 而发送的消息经过一系列辗转之后,最后会被传递到Handler的HandleMessage方法中,最终在HandleMessage方法中Message对象被处理

    3. MessageQueue
    顾名思义,它就是消息队列的意思,它用于存放所有通过hanlder发送过来的消息。 这部分消息会一直存放于消息队列之中,等待被处理。 每一个线程只会由一个MessageQueue对象。 其实从字面上就可以看出,MessageQueue底层数据结构是队列,而且这个队列只存放Message对象。

    4.Looper
    Looper用于管理每个线程中的MessageQueue, 调用Looper的loop()方法后,就会进入一个无限的循环。 每当MessageQueue储存一条信息,Looper就会将这条信息取出, 由Looper按先入先出顺序取出,再根据Message对象的what属性分发给对应的Handler的HandleMessage()方法中。 每个线程只有一个Looper.

    Handler怎么用

    Handler可以分发Message和 Runnable对象进入主线程中, 每个Handler实例都会绑定到创建它的线程中 它由两个作用:
    1.合理调度安排消息和Runnable对象,使他们在将来的某个点执行。
    2. 安排一个动作在不同线程执行。

    Handler中一些常见的方法:
    post(Runnable)直接开启Runnable线程
    postAtTime(Runnable,long)在指定的时间long,开始启动线程
    postDelayed(Runnable long)在延迟long时间后,启动Runnable线程
    sendEmptyMessage(int) 发送指定的消息,通过参数int来区分不同的消息
    sendMessage(Message)发送消息到UI线程中
    sendMessageAtTime(Message,long) 这个long代表的是系统时间,不推荐用
    sendMessageDelayed(Message,long) 此方法long代表调用后几秒后执行。
    sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

    handler基本使用:
    1)在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在 handleMessage 中提供收到消息后相应的处理方法即可。(接收消息,并且更新UI)

    1. 在新启动的线程发送消息。
    public class HandlerActivity extends AppCompatActivity {
     
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                tv.setText("msg.arg1:"+msg.arg1+"--msg.arg2:"+msg.arg2);
            }
        };
        private TextView tv;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_handler);
            initView();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Message msg = Message.obatin();//实例化消息对象
                    msg.arg1 = 99;//携带参数
                    msg.arg2 = 100;//携带参数
                    Object str = new Object();//实例化对象
                    msg.obj = str; //携带参数为实体类对象
                    handler.sendMessage(msg);
                }
            });
            }
        private void initView() {
            tv = (TextView) findViewById(R.id.tv);
        }
    }
    

    总结:
    首先在UI线程我们创建了一个Handler实例对象,无论是匿名内部类还是自定义类生成的Handler实例对象,我们都需要对handleMessage方法进行重写,在此方法中我们可以通过参数来接受msg来写接受消息后如何处理。 接着我们创建一个子线程,在子线程中需要更新ui时,新建一个Message对象,并且将消息的数据记录在这个消息对象Message的内部,比如arg1,arg2,obj等, 在通过前面创建的handler的sendMessage方法把次消息给发送出去, 此时这个Message会放入MessageQueue中等待被处理, 此时MessageQueue的管家Looper会不停的把messageQueue存在的消息取出来,通过回调dispatchMessage方法将消息传递给Handler的handleMessage方法,最终前面提到的消息会被Looper从MessageQueue中取出来传递给handleMessage方法,最终得到处理。

    展开全文
  • android Handler 机制

    2017-02-10 12:20:14
    最近详细了解了一下handler机制的原理,记录一下以防忘记 handler机制涉及一下几个类 Looper、MessageQueue、Handler、Message,理清记者之间的关系,就明白了handler传递消息的具体逻辑 来看一下以上及各类...

    最近详细了解了一下handler机制的原理,记录一下以防忘记

    handler机制涉及一下几个类   Looper、MessageQueue、Handler、Message,理清记者之间的关系,就明白了handler传递消息的具体逻辑


    来看一下以上及各类各自的作用

    Message:就是我们传递的消息实体

    MessageQueue:消息体的集合

    Looper:创建消息队列MessageQueue,启动无限循环从消息队列里不断获取消息,调用回调方法执行相应操作

    Handler:创建消息,关联消息队列,把创建的消息添加到消息队列里面。在handleMessage回调里对消息进行处理


    展开全文
  • Android Handler 机制

    2017-05-25 16:00:28
    Handler机制中包含了四个主要部分:Handler、Message、MessageQuene、Looper 首先来说说Handler Handler可以理解为处理者就是对消息(message)进行对应的处理,同时它也是发送者,消息在发送的时候必须要通过Handler...
  • android Handler机制 消息机制.pdf
  • handler机制能够说是android面试时必考的一项,其思想仍是比较nb的,最近和组内的ios同事聊天时,发现ios也有一套相似的机制,可见handler机制的重要性。在了解事后,作一个简单的总结,加深本身的印象。android1、...
  • android Handler机制

    2016-12-25 20:22:39
    在修改ui界面时遇到错误,特此查询了有关主、子线程的介绍,本篇博文转至/阿敏其人,大解吾惑,转发...什么安卓的消息机制,就是 Handler 运行机制安卓的消息机制有什么用? —— 避免ANR(Application Not Responding
  • android handler 机制

    2014-08-06 09:43:36
    首先要理解handler机制,我们必须
  • 一个Android handler机制的Demo
  • android handler 机制源码 (带部分汉语注释)
  • Android Handler机制实例

    2012-11-22 22:58:29
    Android Handler机制实例,测试可运行,适合初学handler机制
  • handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段。使用起来很简单,就两个...先上图,让大家好理解下handler机制handler机制示例图上面一共出现了几种类,ActivityThread,Handler,MessageQ...
  • android handler机制

    千次阅读 2016-04-26 14:47:33
    概述一般讲handler,会讲到这三个Handler 、 Looper 、Message 这三者涉及到一个概念,叫做异步消息处理线程; UI线程初始化,会通过ThreadLocal创建一个Looper(轮询器),一个线程对应唯一一个Looper,使用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 67,662
精华内容 27,064
关键字:

安卓的handler机制