0%

个人对Handler以及Thread的理解

这两天在写个壁纸软件,功能大致是这样:显示一个ProgressBar,再下载图片URL列表,然后根据URL列表逐个下载图片,下载完一张显示一张,直到全部下载完隐藏ProgressBar。 因为之前对Handler理解有误,以为Handler是建立新线程,与UI线程不同,所以所有的操作都放在Handler里,结果上面的功能是实现了,但是UI还是堵塞,在下载图片的过程中,ProgressBar卡住不动。于是请教论坛网友,得知Handler与UI是同一线程的,用Handler下载数据,UI肯定会卡,建议New一个Thread,把下载功能放这里。于是我把所有代码都放进Thread里,结果编译通过,但是执行出错,DDMS里提示android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. (只有原始创建这个视图层次(view hierachy)的线程才能修改它的视图(view)。)。看来notifyDataSetChanged()还是应该放在与UI同线程的Handler里,结果也证明我的猜想是正确的,现在程序已经完美实现我想要的功能。 下面说说我对Handler以及Thread的理解,Handler与UI同线程,它的最主要功能是负责UI与其他进程之间的通讯,而新建一个Thread才是独立于UI的线程,所有耗时操作必须放这里才不致于UI堵塞。 2013年8月26日更新: 不好意思,以上的理解是错误的或者说,不够深入,误导了不少新人,当时写这篇文章的时候,我也是刚接触Android,希望各位见谅. 其实Android是基于消息机制的,通过Looper、Handler来实现消息循环,在线程间相互通讯.Looper里保存了消息列表,通过Handler发送的消息都会保存在Looper里先,然后在loop()方法里,遍历消息列队,分发消息.Handler负责传送消息,处理消息.So,多线程通讯的原理就是,通过另一个线程handler来发送消息,因为Android里主要是跟UI线程通讯,所以一般就在UI线程创建Handler,在工作线程调用这个Handler来发送消息,但并不表示只有UI线程才能有Hanlder,其实要跟UI线程通讯,Handler在哪创建不是重点,重点是,创建这个Handler时使用的Looper对象在哪. UI线程默认会创建Looper,而工作线程(就是用户自己创建,用于处理耗时操作)默认没有Looper,所以,可以直接在UI线程new Handler,但是在工作线程,需要先调Looper.prepare(),给当前线程创建Looper对象. 如果是调用没有参数的构造方法创建Handler,即new Hanlder(),默认使用的是当前线程的Looper对象. 所以,在工作线程中先Looper.prepare(),再new Hanlder(),这样的Handler是无法与UI线程通讯的.但是Handler还有个带Looper对象参数的构造方法,传入主线程的Looper,另外,Looper类有个静态获取主线程Looper对象的方法:Looper.getMainLooper() so,在工作线程中创建与UI线程通讯的Handler,可以这样: Handler mHandler=new Handler(Looper.getMainLooper()); 无需再传入UI线程的Looper或者Handler对象作参数.