========================================================
作者: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 变量只有在等待时间到了你却还未执行的情况下才有效果。
- 任务一旦开始执行就不会中途退出,无论此时女神是否走了。
代码:
UIKit.java
UIKitHandlerPoster.java
UIKitSyncPost.java
========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41900879
========================================================