Handler机制一点一点带你抛析(1)

来源:互联网 发布:thinkphp开发cms 编辑:程序博客网 时间:2024/06/05 10:03

Handler机制:
原理:Handler机制是安卓提供的一套切换线程操作的工具。使用的场景:应用一般在子线程加载网络数据,然后需要将获取的数据给到视图层做展示。此过程需要切换到主线程然后做更新UI的操作。此时我们会提出一个问题:就是为什么要切换到主线程更新UI在子线程中不能更新么?
答案是不可以的。因为在ViewRootImpl类中存在一个checkThread方法用来检查View更新的线程,如果当前的线程不等于mThread指定的线程那么就会抛出异常,mThread初始化的值就是主线程。代码如下:

    void checkThread() {        if (mThread != Thread.currentThread()) {            throw new CalledFromWrongThreadException(                    "Only the original thread that created a view hierarchy can touch its views.");        }    }

所以我们很容易得就可以得出结论:系统之所以提供Handler,主要原因就是为了解决在子线程中无法访问UI的矛盾。

那么Handler机制的工作原理是什么呢?这里我们先讲讲Handler的大致用法和组成。
Handler的运行需要底层Looper和Message的协助完成。Message算是存储消息的队列,每次Handler发送的消息都会存储到Message队列中。竟然消息存储在队列中,那到底谁读取队列中的信息并且运行呢?没错答案就是Looper。Looper相当于一个无限循环的While每次检查Message队列中是否存在数据,如果存在就将数据提取出来,给到Handler的HandleMessage方法进行处理调用。可以看出Looper相当于一个Handler机制的管家,每时每刻都在盯着message中是否存在数据。那么刚刚说道Handler是如何的切换线程,根据上面的解释我们好像还是有点懵懂。
切换线程的关键点还是在Looper上,看我娓娓道来。Message作为一个存储数据的是不会管当前取数据Looper管家处在什么线程。而Handler也是在不同的线程中发送数据到队列Message中。那么切换线程的工作就只能是Looper来完成了。问题一:为什么管家Looper一定是在主线程中取出数据然后给到Handler进行处理呢?
这里Looper还有一个重要的知识点,每个线程都可以创建或者持有一个Looper专门用来处理Handler发送过来的数据。并且在使用Handler之前需要在使用的线程初始化Looer,如果当前线程不存在Looper就会抛出异常,详细的看代码如下:

``` 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());        }    }    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;}```因为Handler与主线程的Looper进行绑定,所以Handler发送数据到队列中,再由Looper在队列中取数据时因为Looper是在主线程中取的数据,然后将数据交给之前的Handler进行处理。这个过程是在主线程的!可能这个说的有点不是很清楚。下面我会分点讨论。首先:假设我们程序中存在子线程1和主线程main,我们需要将在子线程中获取到的数据交由到主线程main中进行处理。因为这里进行了子线程的切换我们就可以使用Handler机制进行子线程1切换到主线程的操作。首先:我们需要初始化我们的Handler。整么初始化呢?一般我们直接在主线程中new Handler()---上面不是说直接new的话会报looper的缺失异常吗?因为主线程本身就存在Looper所以我们直接new 就可以。然后:我们在子线程1中将获取到的数据使用Handler发送到Message队列中。这个过程发生在子线程中。最后:由主线程的Looper取出Message队列的数据,发送给Handler进行处理--这个过程是发生在主线程中的。看懂上面的表述想必应该都大致明白Handler的机制了吧
阅读全文
1 0
原创粉丝点击