[Android] 任意时刻从子线程切换到主线程的实现原理及加强版

========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41900879
========================================================

Android 的使用中经常会遇到从子线程切换到主线程进行界面更改的情况的;如果在一个 Activity 中进行倒好说一个 Handler 即可解决问题;但是假如很多个界面呢?每个界面都建立一个 Handler 么?太浪费了吧?咱们要的是简洁;要的是效率!走起。。。。

本来打算在原来的文章 [Android] 任意时刻从子线程切换到主线程的实现 上面进行修改的;但是发现没法啊;原来的那个出了些问题导致很难编辑,一编辑就乱的不成样了;无奈新开了一章。我想应该与其中我复制了大量的有样式的代码有关。

在上一章 [Android] 任意时刻从子线程切换到主线程的实现 中介绍了其具体的实现方式;但是没有系统的说一下原理;在这里就叙说一下。

原理

Handler原理:


当然其有很多细节部分没有一一画出来,这里就先过去了;将就看看啊 哈哈。

ToolKit 一键操作原理:


这里直接看或许会有些麻烦;一定要先看看上一章 [Android] 任意时刻从子线程切换到主线程的实现 中的内容后再看。不然这个图片就是一个废图。

New

都说了要加入新的功能,是啥呢?在上一章中说了有一种同步方法;该方法将会等待主线程执行了子线程的任务后,子线程才返回。这种是属于比较赖皮的形式。

假如子线程是女神,主线程是你;现在女神等你做事儿;但是呢你的人缘比较不错有很多女神都把任务给你;而其中一个女神就不乐意了;她就想要是你慢慢的做,我还这么等着你,岂不是太给你面子了。

然后女神就想,我等你半个小时吧;如果半个小时了你做了那我就接受你吧,如果没有那就拜拜吧。

针对这样的时间等待情况我们就需要加入一个新的方法:    public static void runOnMainThreadSync(Runnable runnable, int waitTime, boolean cancel)

原来的 public static void runOnMainThreadSync(Runnable runnable)

    public static void runOnMainThreadSync(Runnable runnable) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            runnable.run();
            return;
        }
        SyncPost poster = new SyncPost(runnable);
        getMainPoster().sync(poster);
        poster.waitRun();
    }
现在我们建立一个新的方法,只需要在上面改动几下。

新的 public static void runOnMainThreadSync(Runnable runnable, int waitTime, boolean cancel):

    public static void runOnMainThreadSync(Runnable runnable, int waitTime, boolean cancel) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            runnable.run();
            return;
        }
        SyncPost poster = new SyncPost(runnable);
        getMainPoster().sync(poster);
        poster.waitRun(waitTime, cancel);
    }
可以看见其中多了两个参数,一个是女神等待的时间:waitTime ;第二个参数就是女神走了后 你究竟还做不做该女神下达的任务(cancel)

女神:子线程
你:主线程

当然对应的 SyncPost 中的 public void waitRun() 方法也需要新添加一个类似的方法,为了解释就直接添加方法了,没有在原来的方法上修改。

原来的:public void waitRun():

    public void waitRun() {
        if (!end) {
            synchronized (this) {
                if (!end) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
新添加的:public void waitRun(int time, boolean cancel):

    public void waitRun(int time, boolean cancel) {
        if (!end) {
            synchronized (this) {
                if (!end) {
                    try {
                        this.wait(time);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        if (!end && cancel)
                            end = true;
                    }
                }
            }
        }
    }
可以看见其中的  this.wait(time); 进行了时间等待。

同时在完成后我们根据情况改变了 END 变量的状态。当然这里改变了,那么你做任务的时候就需要先判断了。

所以原来的执行方法:public void run():

    public void run() {
        synchronized (this) {
            runnable.run();
            end = true;
            try {
                this.notifyAll();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
要更改为:

    public void run() {
        if(!end) {
            synchronized (this) {
                if(!end) {
                    runnable.run();
                    end = true;
                    try {
                        this.notifyAll();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
也就是在进入同步前与同步后分别进行判断该状态是否为 Flase如果是则证明需要执行;那么就进行执行。

代码部分就OK了,大家可以测试测试!

场景

针对上面新加的功能有如下场景:前提(女神叫你做事情;最长等待时间半个小时!)

  • 女神和你在一起,那么立刻就做事情。(此时女神就是主线程的情况,实际工作折就是女神;也可以说是你;因为你也是主线程)
  • 女神等了半个小时然后走了,至于之后你做不做女神给你的这个任务取决于女神的态度
  • 女神还没有等你就开始做了,此时女神压根儿就不会想等待的事情;也就是说不会执行到 this.wait(time);  语句;因为获取到同步块后就退出了。她等待的时间是花在等待进入同步块上。
  • 女神已经开始等待了12分钟了;此时你开始做了你在18分钟内完成了;那么说明是按时完成任务。
  • 女神已经开始等待了12分钟了;此时你开始做了,但是你还需要20分钟完成,女神在你完成前走了;此时不管女神说叫你做还是不做你都会把它做完的;你是个有责任的男人。

总结

  • cancel 变量只有在等待时间到了你却还未执行的情况下才有效果。
  • 任务一旦开始执行就不会中途退出,无论此时女神是否走了。

代码:

ToolKit.java
HandlerPoster.java
SyncPost.java


========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41900879
========================================================

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。