前言: 我们在开发Android过程中,在处理耗时任务和UI交互的过程中,都会将耗时任务放到子线程处理并刷新. 下面我提出的两个问题,相信大多数开发者都会碰到:
1.数据经常需要读取更新,并且比较耗时,需要分步刷新UI.
2.UI界面切换后,如何停止掉子线程里面正在读取的数据而不会将旧数据刷新到新UI界面上.
目前网上大部分教程主要只是简单的Handler.postDelayed(), Thread + Handler, Async等方式, 只适用于简单的一次性刷新. 或许有人会说我可以采用不断地new Thread的方式来创建子线程刷新,然后传message回去更新UI,但是这样的不断地new会有性能消耗大和数据同步的问题.
关于以上这两个问题的解决, 我在这里想要介绍的是使用线程池+Future+handler的配合使用.
为了更好理解异步更新UI的原理,这里先介绍下Thread + Handler + Looper + Message模型, 如下图1所示:
图1清楚给我们展示出了消息队列在Looper里面的处理方式,这里有两个重要的要点: (1)子线程也可以通过Looper管理Message, 但是需要加Looper.prepare() 和Looper.loop()才能实现消息循环; (2)UI主线程无需实现prepare()和loop()因为主线程中已经默认实现了.
现在开始介绍线程池+Future+handler的一些基本概念和使用demo实例.
线程池
是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源.如果在程序中反复创建和销毁线程,将会对程序的反应速度造成严重影响,有时甚至会Crash掉程序.这里我们使用简单的ExecutorService类.
Future<?>
Future模式可以这样来描述:我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时间之后,我就便可以从Future那儿取出结果。就相当于下了一张订货单,一段时间后可以拿着提订单来提货,这期间可以干别的任何事情。其中Future 接口就是订货单,真正处理订单的是Executor类,它根据Future接口的要求来生产产品。
Handler
连接子线程和主线程的桥梁,可以通过sendmessage或者post的方式跟主线程通信.
说了这么多,如果还有对基本概念不太熟悉的童鞋可以先移步到最后的参考文章里看下再回来看本文章,此处直接上代码干货.
方法一:利用sendMessage实现
1 | public class MyActivity extends Activity { |
结果和打印如下图2和3所示:
图4用多次点击来模拟UI不停调用刷新的情况,后台的执行任务会只是保留当前task和最后一次提交的task,中间的task都被Futurecancel掉了.而且当前旧的task也会受到标志位的控制,不会将更新内容sendMessage出来,从而不会影响最后一次UI的刷新.
方法二:利用runnable实现更新:
由于部分方法跟上面一样,所以要看完整代码可以在下面下载,以下只是核心代码.
1 | public void loadToRunnable() { |
代码下载路径:http://download.csdn.NET/detail/jjzhoujun2010/8524159
参考文章:http://yangjingblog.iteye.com/blog/1860590
http://www.eoeandroid.com/thread-274533-1-1.html
http://www.cnblogs.com/qingblog/archive/2012/06/27/2566021.html
http://my.oschina.net/bairrfhoinn/blog/177639
http://blog.csdn.net/lyf_007217/article/details/8542238
原创文章,欢迎转载,转载请注明:ifish.site
原始CSDN博客已经迁移,原路径:CSDN
作者:JaydenZhou